blob: b35de59d7fcc8d1de4a8d8c54f106946dc0d6d7f [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;
lucasline252a742019-03-12 13:08:03 +080031import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090032import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060033import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
34import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
35import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
36import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
38import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
44import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090045import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060046import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080047import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060048import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
52import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
53import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
54import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
55import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090056import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060057import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
58import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080059import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
60import static android.net.NetworkPolicyManager.RULE_NONE;
61import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
62import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060063
64import static com.android.internal.util.TestUtils.waitForIdleHandler;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090065import static com.android.internal.util.TestUtils.waitForIdleLooper;
junyulai7c469172019-01-16 20:23:34 +080066import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090067
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090068import static org.junit.Assert.assertEquals;
69import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080070import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090071import static org.junit.Assert.assertNotNull;
72import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060073import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090074import static org.junit.Assert.fail;
Erik Klinee89953b2018-01-11 16:11:10 +090075import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +090076import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060077import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090078import static org.mockito.Mockito.doAnswer;
79import static org.mockito.Mockito.doNothing;
Erik Kline117e7f32018-03-04 21:01:01 +090080import static org.mockito.Mockito.eq;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080081import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060082import static org.mockito.Mockito.never;
83import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090084import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090085import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +090086import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060087import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -070088import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090089import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070090
junyulai7c469172019-01-16 20:23:34 +080091import android.annotation.NonNull;
Lorenzo Colitti73b209382016-09-15 22:18:09 +090092import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040093import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040094import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +090095import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090096import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070097import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040098import android.content.Intent;
99import android.content.IntentFilter;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900100import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400101import android.net.ConnectivityManager;
102import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900103import android.net.ConnectivityManager.PacketKeepalive;
104import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900105import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900106import android.net.ConnectivityThread;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800107import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900108import android.net.INetworkMonitor;
109import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800110import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700111import android.net.INetworkPolicyManager;
112import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800113import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900114import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800115import android.net.IpSecManager;
116import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900117import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700118import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700119import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400120import android.net.Network;
121import android.net.NetworkAgent;
122import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700123import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700124import android.net.NetworkInfo;
125import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400126import android.net.NetworkMisc;
127import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700128import android.net.NetworkSpecifier;
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900129import android.net.NetworkStackClient;
Varun Anand02c50ef2019-02-07 14:13:13 -0800130import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100131import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000132import android.net.ProxyInfo;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700133import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800134import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900135import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900136import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900137import android.net.shared.NetworkMonitorUtils;
138import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900139import android.net.util.MultinetworkPolicyTracker;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400140import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700141import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700142import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700143import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900144import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900145import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700146import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800147import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700148import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000149import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800150import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900151import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900152import android.os.UserHandle;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900153import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800154import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900155import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800156import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100157import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700158import android.util.Log;
Etan Cohenae574a82019-01-08 12:09:18 -0800159import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700160
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800161import androidx.test.InstrumentationRegistry;
162import androidx.test.filters.SmallTest;
163import androidx.test.runner.AndroidJUnit4;
164
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900165import com.android.internal.net.VpnConfig;
Varun Anand02c50ef2019-02-07 14:13:13 -0800166import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900167import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900168import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900169import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900170import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900171import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900172import com.android.server.connectivity.DefaultNetworkMetrics;
173import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900174import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800175import com.android.server.connectivity.Nat464Xlat;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000176import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800177import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900178import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900179import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900180import com.android.server.net.NetworkPolicyManagerInternal;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400181
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900182import org.junit.After;
183import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900184import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900185import org.junit.Test;
186import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900187import org.mockito.ArgumentCaptor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900188import org.mockito.Mock;
189import org.mockito.MockitoAnnotations;
190import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900191import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900192
junyulai0c666972019-03-04 22:45:36 +0800193import java.io.IOException;
194import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800195import java.net.Inet4Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700196import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900197import java.net.InetSocketAddress;
198import java.net.Socket;
junyulai4a192e22018-06-13 15:00:37 +0800199import java.net.UnknownHostException;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400200import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900201import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100202import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800203import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500204import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100205import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900206import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100207import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900208import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800209import java.util.concurrent.Executor;
junyulaie4135282019-01-03 18:50:15 +0800210import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800211import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900212import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900213import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700214import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900215import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700216
217/**
218 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400219 *
220 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900221 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700222 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900223@RunWith(AndroidJUnit4.class)
224@SmallTest
225public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700226 private static final String TAG = "ConnectivityServiceTest";
227
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900228 private static final int TIMEOUT_MS = 500;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900229 private static final int TEST_LINGER_DELAY_MS = 250;
230 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
231 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
232 // timeout. For this, our assertions should run fast enough to leave less than
233 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
234 // supposedly fired, and the time we call expectCallback.
235 private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900236 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
237 // complete before callbacks are verified.
238 private final static int TEST_REQUEST_TIMEOUT_MS = 150;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900239
junyulai4a192e22018-06-13 15:00:37 +0800240 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700241 private static final String MOBILE_IFNAME = "test_rmnet_data0";
242 private static final String WIFI_IFNAME = "test_wlan0";
243
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900244 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400245 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900246 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400247 private MockNetworkAgent mWiFiNetworkAgent;
248 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900249 private MockNetworkAgent mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900250 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900251 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800252 private INetworkPolicyListener mPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700253
Hugo Benichi64901e52017-10-19 14:42:40 +0900254 @Mock IpConnectivityMetrics.Logger mMetricsService;
255 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900256 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600257 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800258 @Mock INetworkPolicyManager mNpm;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800259 @Mock INetd mMockNetd;
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900260 @Mock NetworkStackClient mNetworkStack;
Hugo Benichi64901e52017-10-19 14:42:40 +0900261
Erik Klinee89953b2018-01-11 16:11:10 +0900262 private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
263
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900264 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
265 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
266 // reflect the state of our test ConnectivityService.
267 private class WrappedConnectivityManager extends ConnectivityManager {
268 private Network mFakeBoundNetwork;
269
270 public synchronized boolean bindProcessToNetwork(Network network) {
271 mFakeBoundNetwork = network;
272 return true;
273 }
274
275 public synchronized Network getBoundNetworkForProcess() {
276 return mFakeBoundNetwork;
277 }
278
279 public WrappedConnectivityManager(Context context, ConnectivityService service) {
280 super(context, service);
281 }
282 }
283
Paul Jensend7b6ca92015-05-13 14:05:12 -0400284 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900285 private final MockContentResolver mContentResolver;
286
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900287 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900288 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900289
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900290 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400291 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900292
293 mResources = spy(base.getResources());
294 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
295 thenReturn(new String[] {
296 "wifi,1,1,1,-1,true",
297 "mobile,0,0,0,-1,true",
298 "mobile_mms,2,0,2,60000,true",
299 });
300
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900301 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900302 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400303 }
304
305 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900306 public void startActivityAsUser(Intent intent, UserHandle handle) {
307 mStartedActivities.offer(intent);
308 }
309
310 public Intent expectStartActivityIntent(int timeoutMs) {
311 Intent intent = null;
312 try {
313 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
314 } catch (InterruptedException e) {}
315 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
316 return intent;
317 }
318
319 public void expectNoStartActivityIntent(int timeoutMs) {
320 try {
321 assertNull("Received unexpected Intent to start activity",
322 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
323 } catch (InterruptedException e) {}
324 }
325
326 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900327 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900328 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
329 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900330 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400331 return super.getSystemService(name);
332 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900333
334 @Override
335 public ContentResolver getContentResolver() {
336 return mContentResolver;
337 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900338
339 @Override
340 public Resources getResources() {
341 return mResources;
342 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400343 }
344
Hugo Benichi669f0232017-06-29 22:58:39 +0900345 public void waitForIdle(int timeoutMsAsInt) {
346 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900347 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
348 waitForIdle(mCellNetworkAgent, timeoutMs);
349 waitForIdle(mWiFiNetworkAgent, timeoutMs);
350 waitForIdle(mEthernetNetworkAgent, timeoutMs);
351 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900352 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900353 }
354
Hugo Benichi669f0232017-06-29 22:58:39 +0900355 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900356 if (agent == null) {
357 return;
358 }
359 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
360 }
361
362 private void waitForIdle() {
363 waitForIdle(TIMEOUT_MS);
364 }
365
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900366 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900367 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900368 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
369
370 // Tests that waitForIdle returns immediately if the service is already idle.
371 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900372 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900373 }
374
375 // Bring up a network that we can use to send messages to ConnectivityService.
376 ConditionVariable cv = waitForConnectivityBroadcasts(1);
377 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
378 mWiFiNetworkAgent.connect(false);
379 waitFor(cv);
380 Network n = mWiFiNetworkAgent.getNetwork();
381 assertNotNull(n);
382
383 // Tests that calling waitForIdle waits for messages to be processed.
384 for (int i = 0; i < attempts; i++) {
385 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900386 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900387 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
388 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900389 }
390
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900391 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
392 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800393 @Ignore
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900394 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900395 // Bring up a network that we can use to send messages to ConnectivityService.
396 ConditionVariable cv = waitForConnectivityBroadcasts(1);
397 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
398 mWiFiNetworkAgent.connect(false);
399 waitFor(cv);
400 Network n = mWiFiNetworkAgent.getNetwork();
401 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900402
403 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900404 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900405 for (int i = 0; i < attempts; i++) {
406 mWiFiNetworkAgent.setSignalStrength(i);
407 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
408 // We hit a race condition, as expected. Pass the test.
409 return;
410 }
411 }
412
413 // No race? There is a bug in this test.
414 fail("expected race condition at least once in " + attempts + " attempts");
415 }
416
Paul Jensend7b6ca92015-05-13 14:05:12 -0400417 private class MockNetworkAgent {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900418 private final INetworkMonitor mNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400419 private final NetworkInfo mNetworkInfo;
420 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900421 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400422 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400423 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700424 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400425 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400426 private NetworkAgent mNetworkAgent;
junyulai0c666972019-03-04 22:45:36 +0800427 private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
junyulai48eac1d42018-12-27 17:25:29 +0800428 private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900429 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400430 // Contains the redirectUrl from networkStatus(). Before reading, wait for
431 // mNetworkStatusReceived.
432 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400433
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900434 private INetworkMonitorCallbacks mNmCallbacks;
435 private int mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
436 private String mNmValidationRedirectUrl = null;
437 private boolean mNmProvNotificationRequested = false;
438
439 void setNetworkValid() {
440 mNmValidationResult = NETWORK_TEST_RESULT_VALID;
441 mNmValidationRedirectUrl = null;
442 }
443
444 void setNetworkInvalid() {
445 mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
446 mNmValidationRedirectUrl = null;
447 }
448
449 void setNetworkPortal(String redirectUrl) {
450 setNetworkInvalid();
451 mNmValidationRedirectUrl = redirectUrl;
452 }
453
lucasline252a742019-03-12 13:08:03 +0800454 void setNetworkPartial() {
455 mNmValidationResult = NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
456 mNmValidationRedirectUrl = null;
457 }
458
Paul Jensend7b6ca92015-05-13 14:05:12 -0400459 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100460 this(transport, new LinkProperties());
461 }
462
463 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400464 final int type = transportToLegacyType(transport);
Chalard Jean0b214af2018-01-12 17:22:49 +0900465 final String typeName = ConnectivityManager.getNetworkTypeName(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400466 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
467 mNetworkCapabilities = new NetworkCapabilities();
468 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400469 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900470 case TRANSPORT_ETHERNET:
471 mScore = 70;
472 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400473 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400474 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400475 break;
476 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400477 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400478 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900479 case TRANSPORT_WIFI_AWARE:
480 mScore = 20;
481 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900482 case TRANSPORT_VPN:
Chalard Jeanb552c462018-02-21 18:43:54 +0900483 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
Chalard Jeandda156a2018-01-10 21:19:32 +0900484 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
Chalard Jean0b214af2018-01-12 17:22:49 +0900485 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400486 default:
487 throw new UnsupportedOperationException("unimplemented network type");
488 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900489 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900490 mHandlerThread.start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900491
492 mNetworkMonitor = mock(INetworkMonitor.class);
493 final Answer validateAnswer = inv -> {
494 new Thread(this::onValidationRequested).start();
495 return null;
496 };
497
498 try {
499 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected();
500 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
501 } catch (RemoteException e) {
502 fail(e.getMessage());
503 }
504
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900505 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900506 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
507 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
508 doNothing().when(mNetworkStack).makeNetworkMonitor(
509 nmNetworkCaptor.capture(),
510 any() /* name */,
511 nmCbCaptor.capture());
512
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900513 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
514 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Chalard Jean08577fc2018-05-02 21:14:54 +0900515 linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900516 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900517 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900518
519 @Override
junyulaie4135282019-01-03 18:50:15 +0800520 public void startSocketKeepalive(Message msg) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900521 int slot = msg.arg1;
522 if (mExpectedKeepaliveSlot != null) {
523 assertEquals((int) mExpectedKeepaliveSlot, slot);
524 }
junyulaie4135282019-01-03 18:50:15 +0800525 onSocketKeepaliveEvent(slot, mStartKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900526 }
527
528 @Override
junyulaie4135282019-01-03 18:50:15 +0800529 public void stopSocketKeepalive(Message msg) {
530 onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900531 }
Paul Jensen232437312016-04-06 09:51:26 -0400532
533 @Override
534 public void networkStatus(int status, String redirectUrl) {
535 mRedirectUrl = redirectUrl;
536 mNetworkStatusReceived.open();
537 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700538
539 @Override
540 protected void preventAutomaticReconnect() {
541 mPreventReconnectReceived.open();
542 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400543 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900544
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900545 assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900546 mNmCallbacks = nmCbCaptor.getValue();
547
548 try {
549 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
550 } catch (RemoteException e) {
551 fail(e.getMessage());
552 }
553
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900554 // Waits for the NetworkAgent to be registered, which includes the creation of the
555 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900556 waitForIdle();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900557 }
558
559 private void onValidationRequested() {
560 try {
561 if (mNmProvNotificationRequested
562 && mNmValidationResult == NETWORK_TEST_RESULT_VALID) {
563 mNmCallbacks.hideProvisioningNotification();
564 mNmProvNotificationRequested = false;
565 }
566
567 mNmCallbacks.notifyNetworkTested(
568 mNmValidationResult, mNmValidationRedirectUrl);
569
570 if (mNmValidationRedirectUrl != null) {
571 mNmCallbacks.showProvisioningNotification(
Remi NGUYEN VAN9c5d9642019-02-07 21:29:57 +0900572 "test_provisioning_notif_action", "com.android.test.package");
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900573 mNmProvNotificationRequested = true;
574 }
575 } catch (RemoteException e) {
576 fail(e.getMessage());
577 }
Paul Jensen3d911462015-06-12 06:40:24 -0400578 }
579
580 public void adjustScore(int change) {
581 mScore += change;
582 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400583 }
584
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900585 public void explicitlySelected(boolean acceptUnvalidated) {
586 mNetworkAgent.explicitlySelected(acceptUnvalidated);
587 }
588
Paul Jensen85cf78e2015-06-25 13:25:07 -0400589 public void addCapability(int capability) {
590 mNetworkCapabilities.addCapability(capability);
591 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
592 }
593
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900594 public void removeCapability(int capability) {
595 mNetworkCapabilities.removeCapability(capability);
596 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
597 }
598
Chalard Jean0b214af2018-01-12 17:22:49 +0900599 public void setUids(Set<UidRange> uids) {
600 mNetworkCapabilities.setUids(uids);
601 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
602 }
603
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900604 public void setSignalStrength(int signalStrength) {
605 mNetworkCapabilities.setSignalStrength(signalStrength);
606 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
607 }
608
Etan Cohena7434272017-04-03 12:17:51 -0700609 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
610 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900611 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
612 }
613
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900614 public void setNetworkCapabilities(NetworkCapabilities nc,
615 boolean sendToConnectivityService) {
616 mNetworkCapabilities.set(nc);
617 if (sendToConnectivityService) {
618 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
619 }
620 }
621
Paul Jensene0988542015-06-25 15:30:08 -0400622 public void connectWithoutInternet() {
623 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
624 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
625 }
626
Paul Jensend7b6ca92015-05-13 14:05:12 -0400627 /**
Paul Jensene0988542015-06-25 15:30:08 -0400628 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400629 * @param validated Indicate if network should pretend to be validated.
630 */
631 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900632 connect(validated, true);
633 }
634
635 /**
636 * Transition this NetworkAgent to CONNECTED state.
637 * @param validated Indicate if network should pretend to be validated.
638 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
639 */
640 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900641 assertEquals("MockNetworkAgents can only be connected once",
642 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400643 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
644
Paul Jensend7b6ca92015-05-13 14:05:12 -0400645 NetworkCallback callback = null;
646 final ConditionVariable validatedCv = new ConditionVariable();
647 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900648 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400649 NetworkRequest request = new NetworkRequest.Builder()
650 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900651 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400652 .build();
653 callback = new NetworkCallback() {
654 public void onCapabilitiesChanged(Network network,
655 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400656 if (network.equals(getNetwork()) &&
657 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400658 validatedCv.open();
659 }
660 }
661 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400662 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400663 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900664 if (hasInternet) {
665 addCapability(NET_CAPABILITY_INTERNET);
666 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400667
Paul Jensene0988542015-06-25 15:30:08 -0400668 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400669
670 if (validated) {
671 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400672 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900673 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400674 }
675
676 if (callback != null) mCm.unregisterNetworkCallback(callback);
677 }
678
Paul Jensen232437312016-04-06 09:51:26 -0400679 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900680 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400681 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400682 }
683
lucasline252a742019-03-12 13:08:03 +0800684 public void connectWithPartialConnectivity() {
685 setNetworkPartial();
686 connect(false);
687 }
688
Erik Kline1d3db322017-02-28 16:20:20 +0900689 public void suspend() {
690 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
691 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
692 }
693
Chalard Jean804b8fb2018-01-30 22:41:41 +0900694 public void resume() {
695 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
696 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
697 }
698
Paul Jensend7b6ca92015-05-13 14:05:12 -0400699 public void disconnect() {
700 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
701 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
702 }
703
704 public Network getNetwork() {
705 return new Network(mNetworkAgent.netId);
706 }
Paul Jensene0988542015-06-25 15:30:08 -0400707
Calvin On1f64f3f2016-10-11 15:10:46 -0700708 public ConditionVariable getPreventReconnectReceived() {
709 return mPreventReconnectReceived;
710 }
711
Paul Jensene0988542015-06-25 15:30:08 -0400712 public ConditionVariable getDisconnectedCV() {
713 return mDisconnected;
714 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400715
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900716 public void sendLinkProperties(LinkProperties lp) {
717 mNetworkAgent.sendLinkProperties(lp);
718 }
719
720 public void setStartKeepaliveError(int error) {
721 mStartKeepaliveError = error;
722 }
723
724 public void setStopKeepaliveError(int error) {
725 mStopKeepaliveError = error;
726 }
727
728 public void setExpectedKeepaliveSlot(Integer slot) {
729 mExpectedKeepaliveSlot = slot;
730 }
Paul Jensen232437312016-04-06 09:51:26 -0400731
732 public String waitForRedirectUrl() {
733 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
734 return mRedirectUrl;
735 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900736
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900737 public NetworkAgent getNetworkAgent() {
738 return mNetworkAgent;
739 }
740
Chalard Jean804b8fb2018-01-30 22:41:41 +0900741 public NetworkCapabilities getNetworkCapabilities() {
742 return mNetworkCapabilities;
743 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400744 }
745
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900746 /**
747 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
748 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean08577fc2018-05-02 21:14:54 +0900749 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900750 * expectRemoveRequests.
751 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700752 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400753 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
754 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400755 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700756
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900757 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean08577fc2018-05-02 21:14:54 +0900758 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
759 // once, then cause some other thread to add or remove requests, then call
760 // waitForRequests().
761 // It is not possible to wait for both add and remove requests. When adding, the queue
762 // contains the expected score. When removing, the value is unused, all matters is the
763 // number of objects in the queue.
764 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900765
766 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean08577fc2018-05-02 21:14:54 +0900767 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900768 private boolean mExpectingAdditions;
769
Etan Cohenae574a82019-01-08 12:09:18 -0800770 // Used to collect the networks requests managed by this factory. This is a duplicate of
771 // the internal information stored in the NetworkFactory (which is private).
772 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
773
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700774 public MockNetworkFactory(Looper looper, Context context, String logTag,
775 NetworkCapabilities filter) {
776 super(looper, context, logTag, filter);
Chalard Jean08577fc2018-05-02 21:14:54 +0900777 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700778 }
779
780 public int getMyRequestCount() {
781 return getRequestCount();
782 }
783
784 protected void startNetwork() {
785 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400786 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700787 }
788
789 protected void stopNetwork() {
790 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400791 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700792 }
793
794 public boolean getMyStartRequested() {
795 return mNetworkStarted.get();
796 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400797
798 public ConditionVariable getNetworkStartedCV() {
799 mNetworkStartedCV.close();
800 return mNetworkStartedCV;
801 }
802
803 public ConditionVariable getNetworkStoppedCV() {
804 mNetworkStoppedCV.close();
805 return mNetworkStoppedCV;
806 }
807
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900808 @Override
Chalard Jean08577fc2018-05-02 21:14:54 +0900809 protected void handleAddRequest(NetworkRequest request, int score,
810 int factorySerialNumber) {
811 synchronized (mExpectations) {
812 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900813
Chalard Jean08577fc2018-05-02 21:14:54 +0900814 assertNotNull("Added more requests than expected (" + request + " score : "
815 + score + ")", expectedScore);
816 // If we're expecting anything, we must be expecting additions.
817 if (!mExpectingAdditions) {
818 fail("Can't add requests while expecting requests to be removed");
819 }
820 if (expectedScore != score) {
821 fail("Expected score was " + expectedScore + " but actual was " + score
822 + " in added request");
823 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900824
Chalard Jean08577fc2018-05-02 21:14:54 +0900825 // Add the request.
Etan Cohenae574a82019-01-08 12:09:18 -0800826 mNetworkRequests.put(request.requestId, request);
Chalard Jean08577fc2018-05-02 21:14:54 +0900827 super.handleAddRequest(request, score, factorySerialNumber);
828 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900829 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400830 }
831
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900832 @Override
833 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900834 synchronized (mExpectations) {
835 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900836
Chalard Jean08577fc2018-05-02 21:14:54 +0900837 assertTrue("Removed more requests than expected", expectedScore != null);
838 // If we're expecting anything, we must be expecting removals.
839 if (mExpectingAdditions) {
840 fail("Can't remove requests while expecting requests to be added");
841 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900842
Chalard Jean08577fc2018-05-02 21:14:54 +0900843 // Remove the request.
Etan Cohenae574a82019-01-08 12:09:18 -0800844 mNetworkRequests.remove(request.requestId);
Chalard Jean08577fc2018-05-02 21:14:54 +0900845 super.handleRemoveRequest(request);
846 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900847 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400848 }
849
Etan Cohenae574a82019-01-08 12:09:18 -0800850 // Trigger releasing the request as unfulfillable
851 public void triggerUnfulfillable(NetworkRequest r) {
852 super.releaseRequestAsUnfulfillableByAnyFactory(r);
853 }
854
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900855 private void assertNoExpectations() {
Chalard Jean08577fc2018-05-02 21:14:54 +0900856 if (mExpectations.size() != 0) {
857 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900858 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400859 }
860
Chalard Jean08577fc2018-05-02 21:14:54 +0900861 // Expects that requests with the specified scores will be added.
862 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900863 assertNoExpectations();
864 mExpectingAdditions = true;
Chalard Jean08577fc2018-05-02 21:14:54 +0900865 for (int score : scores) {
866 mExpectations.add(score);
867 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400868 }
869
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900870 // Expects that count requests will be removed.
871 public void expectRemoveRequests(final int count) {
872 assertNoExpectations();
873 mExpectingAdditions = false;
Chalard Jean08577fc2018-05-02 21:14:54 +0900874 for (int i = 0; i < count; ++i) {
875 mExpectations.add(0); // For removals the score is ignored so any value will do.
876 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900877 }
878
879 // Waits for the expected request additions or removals to happen within a timeout.
880 public void waitForRequests() throws InterruptedException {
Chalard Jean08577fc2018-05-02 21:14:54 +0900881 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
882 synchronized (mExpectations) {
883 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
884 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
885 }
886 }
887 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900888 final String msg = count + " requests still not " +
889 (mExpectingAdditions ? "added" : "removed") +
890 " after " + TIMEOUT_MS + " ms";
891 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900892 }
893
Etan Cohenae574a82019-01-08 12:09:18 -0800894 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
895 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900896 waitForRequests();
897 assertEquals(count, getMyRequestCount());
Etan Cohenae574a82019-01-08 12:09:18 -0800898 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400899 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700900 }
901
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900902 private static Looper startHandlerThreadAndReturnLooper() {
903 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
904 handlerThread.start();
905 return handlerThread.getLooper();
906 }
907
908 private class MockVpn extends Vpn {
909 // TODO : the interactions between this mock and the mock network agent are too
910 // hard to get right at this moment, because it's unclear in which case which
911 // target needs to get a method call or both, and in what order. It's because
912 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
913 // parent class of MockVpn agent wants that responsibility.
914 // That being said inside the test it should be possible to make the interactions
915 // harder to get wrong with precise speccing, judicious comments, helper methods
916 // and a few sprinkled assertions.
917
918 private boolean mConnected = false;
919 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
920 // not inherit from NetworkAgent.
921 private MockNetworkAgent mMockNetworkAgent;
922
923 public MockVpn(int userId) {
924 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
925 userId);
926 }
927
928 public void setNetworkAgent(MockNetworkAgent agent) {
929 waitForIdle(agent, TIMEOUT_MS);
930 mMockNetworkAgent = agent;
931 mNetworkAgent = agent.getNetworkAgent();
932 mNetworkCapabilities.set(agent.getNetworkCapabilities());
933 }
934
935 public void setUids(Set<UidRange> uids) {
936 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800937 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900938 }
939
940 @Override
941 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800942 if (mMockNetworkAgent == null) {
943 return NETID_UNSET;
944 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900945 return mMockNetworkAgent.getNetwork().netId;
946 }
947
948 @Override
949 public boolean appliesToUid(int uid) {
950 return mConnected; // Trickery to simplify testing.
951 }
952
953 @Override
954 protected boolean isCallerEstablishedOwnerLocked() {
955 return mConnected; // Similar trickery
956 }
957
Varun Anandc51b06d2019-02-25 17:22:02 -0800958 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900959 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
960 mConnected = true;
961 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -0800962 mConfig.isMetered = isAlwaysMetered;
963 }
964
965 public void connectAsAlwaysMetered() {
966 connect(true /* isAlwaysMetered */);
967 }
968
969 public void connect() {
970 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900971 }
972
973 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -0800974 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
975 if (!mConnected) return null;
976 super.updateCapabilities(defaultNetwork);
977 // Because super.updateCapabilities will update the capabilities of the agent but
978 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900979 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -0800980 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900981 }
982
983 private void copyCapabilitiesToNetworkAgent() {
984 if (null != mMockNetworkAgent) {
985 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
986 false /* sendToConnectivityService */);
987 }
988 }
989
990 public void disconnect() {
991 mConnected = false;
992 mConfig = null;
993 }
994 }
995
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900996 private class FakeWakeupMessage extends WakeupMessage {
997 private static final int UNREASONABLY_LONG_WAIT = 1000;
998
999 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
1000 super(context, handler, cmdName, cmd);
1001 }
1002
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001003 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
1004 int arg1, int arg2, Object obj) {
1005 super(context, handler, cmdName, cmd, arg1, arg2, obj);
1006 }
1007
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001008 @Override
1009 public void schedule(long when) {
1010 long delayMs = when - SystemClock.elapsedRealtime();
1011 if (delayMs < 0) delayMs = 0;
1012 if (delayMs > UNREASONABLY_LONG_WAIT) {
1013 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
1014 "ms into the future: " + delayMs);
1015 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001016 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
1017 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001018 }
1019
1020 @Override
1021 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001022 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001023 }
1024
1025 @Override
1026 public void onAlarm() {
1027 throw new AssertionError("Should never happen. Update this fake.");
1028 }
1029 }
1030
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001031 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +09001032 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001033 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -04001034
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001035 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001036 super(c, h, r);
1037 }
1038
1039 @Override
1040 public boolean configRestrictsAvoidBadWifi() {
1041 return configRestrictsAvoidBadWifi;
1042 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001043
1044 @Override
1045 public int configMeteredMultipathPreference() {
1046 return configMeteredMultipathPreference;
1047 }
Erik Kline065ab6e2016-10-02 18:02:14 +09001048 }
1049
1050 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001051 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001052 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +09001053
Paul Jensend7b6ca92015-05-13 14:05:12 -04001054 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001055 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001056 IpConnectivityLog log, INetd netd) {
Hugo Benichif9fdf872016-07-28 17:53:06 +09001057 super(context, netManager, statsService, policyManager, log);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001058 mNetd = netd;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001059 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001060 }
1061
1062 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001063 protected MockableSystemProperties getSystemProperties() {
1064 // Minimal approach to overriding system properties: let most calls fall through to real
1065 // device values, and only override ones values that are important to this test.
1066 mSystemProperties = spy(new MockableSystemProperties());
1067 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1068 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1069 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001070 }
Paul Jensen67b0b072015-06-10 11:22:17 -04001071
1072 @Override
Mike Yuf9729752018-08-17 15:22:05 +08001073 protected Tethering makeTethering() {
1074 return mock(Tethering.class);
1075 }
1076
1077 @Override
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001078 protected ProxyTracker makeProxyTracker() {
1079 return mock(ProxyTracker.class);
1080 }
1081
1082 @Override
Paul Jensen67b0b072015-06-10 11:22:17 -04001083 protected int reserveNetId() {
1084 while (true) {
1085 final int netId = super.reserveNetId();
1086
1087 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1088 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001089 Context context = InstrumentationRegistry.getContext();
1090 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -04001091 boolean overlaps = false;
1092 for (Network network : networks) {
1093 if (netId == network.netId) {
1094 overlaps = true;
1095 break;
1096 }
1097 }
1098 if (overlaps) continue;
1099
1100 return netId;
1101 }
1102 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001103
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001104 @Override
1105 protected boolean queryUserAccess(int uid, int netId) {
1106 return true;
1107 }
1108
junyulai4a192e22018-06-13 15:00:37 +08001109 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1110 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1111 }
1112
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001113 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001114 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +09001115 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001116 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +09001117 return tracker;
1118 }
1119
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001120 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1121 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001122 }
1123
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001124 @Override
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +09001125 protected NetworkStackClient getNetworkStack() {
1126 return mNetworkStack;
1127 }
1128
1129 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +09001130 public WakeupMessage makeWakeupMessage(
1131 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1132 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001133 }
1134
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001135 @Override
1136 public boolean hasService(String name) {
1137 // Currenty, the only relevant service that ConnectivityService checks for is
1138 // ETHERNET_SERVICE.
1139 return Context.ETHERNET_SERVICE.equals(name);
1140 }
1141
Hugo Benichi64901e52017-10-19 14:42:40 +09001142 @Override
1143 protected IpConnectivityMetrics.Logger metricsLogger() {
1144 return mMetricsService;
1145 }
1146
dalyk1fcb7392018-03-05 12:42:22 -05001147 @Override
1148 protected void registerNetdEventCallback() {
1149 }
1150
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001151 public void mockVpn(int uid) {
1152 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001153 int userId = UserHandle.getUserId(uid);
1154 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001155 // This has no effect unless the VPN is actually connected, because things like
1156 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1157 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001158 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001159 }
1160 }
1161
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001162 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001163 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001164 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001165
1166 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001167 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001168 }
Mike Yuf9729752018-08-17 15:22:05 +08001169
1170 public void setUidRulesChanged(int uidRules) {
1171 try {
1172 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1173 } catch (RemoteException ignored) {
1174 }
1175 }
1176
1177 public void setRestrictBackgroundChanged(boolean restrictBackground) {
1178 try {
1179 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1180 } catch (RemoteException ignored) {
1181 }
1182 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001183 }
1184
Paul Jensen3d911462015-06-12 06:40:24 -04001185 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001186 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1187 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001188 */
1189 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001190 if (conditionVariable.block(TIMEOUT_MS)) {
1191 return;
1192 }
1193 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001194 }
1195
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001196 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001197 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001198 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001199
Hugo Benichi64901e52017-10-19 14:42:40 +09001200 MockitoAnnotations.initMocks(this);
1201 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1202
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001203 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1204 // http://b/25897652 .
1205 if (Looper.myLooper() == null) {
1206 Looper.prepare();
1207 }
1208
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001209 FakeSettingsProvider.clearSettingsProvider();
1210 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1211 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001212 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1213 LocalServices.addService(
1214 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001215
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001216 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001217 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001218 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001219 mNpm,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001220 mock(IpConnectivityLog.class),
1221 mMockNetd);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001222
Mike Yuf9729752018-08-17 15:22:05 +08001223 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1224 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1225 verify(mNpm).registerListener(policyListenerCaptor.capture());
1226 mPolicyListener = policyListenerCaptor.getValue();
1227
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001228 // Create local CM before sending system ready so that we can answer
1229 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001230 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001231 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001232 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001233 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001234
1235 // Ensure that the default setting for Captive Portals is used for most tests
1236 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001237 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001238 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001239 }
1240
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001241 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001242 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001243 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001244 if (mCellNetworkAgent != null) {
1245 mCellNetworkAgent.disconnect();
1246 mCellNetworkAgent = null;
1247 }
1248 if (mWiFiNetworkAgent != null) {
1249 mWiFiNetworkAgent.disconnect();
1250 mWiFiNetworkAgent = null;
1251 }
1252 if (mEthernetNetworkAgent != null) {
1253 mEthernetNetworkAgent.disconnect();
1254 mEthernetNetworkAgent = null;
1255 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001256 FakeSettingsProvider.clearSettingsProvider();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001257 }
1258
Hugo Benichibb91c572017-05-22 10:44:02 +09001259 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001260 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001261 case TRANSPORT_ETHERNET:
1262 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001263 case TRANSPORT_WIFI:
1264 return TYPE_WIFI;
1265 case TRANSPORT_CELLULAR:
1266 return TYPE_MOBILE;
1267 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001268 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001269 }
1270 }
1271
1272 private void verifyActiveNetwork(int transport) {
1273 // Test getActiveNetworkInfo()
1274 assertNotNull(mCm.getActiveNetworkInfo());
1275 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1276 // Test getActiveNetwork()
1277 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001278 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001279 if (!NetworkCapabilities.isValidTransport(transport)) {
1280 throw new IllegalStateException("Unknown transport " + transport);
1281 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001282 switch (transport) {
1283 case TRANSPORT_WIFI:
1284 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1285 break;
1286 case TRANSPORT_CELLULAR:
1287 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1288 break;
1289 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001290 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001291 }
1292 // Test getNetworkInfo(Network)
1293 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001294 assertEquals(transportToLegacyType(transport),
1295 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001296 // Test getNetworkCapabilities(Network)
1297 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1298 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1299 }
1300
1301 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001302 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001303 // Test getActiveNetworkInfo()
1304 assertNull(mCm.getActiveNetworkInfo());
1305 // Test getActiveNetwork()
1306 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001307 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001308 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001309 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001310 }
1311
1312 /**
1313 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1314 * broadcasts are received.
1315 */
1316 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1317 final ConditionVariable cv = new ConditionVariable();
1318 mServiceContext.registerReceiver(new BroadcastReceiver() {
1319 private int remaining = count;
1320 public void onReceive(Context context, Intent intent) {
1321 if (--remaining == 0) {
1322 cv.open();
1323 mServiceContext.unregisterReceiver(this);
1324 }
1325 }
1326 }, new IntentFilter(CONNECTIVITY_ACTION));
1327 return cv;
1328 }
1329
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001330 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001331 public void testNetworkTypes() {
1332 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1333 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1334 // will fail. Failing here is much easier to debug.
1335 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1336 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001337 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1338 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1339
1340 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1341 // mocks, this assert exercises the ConnectivityService code path that ensures that
1342 // TYPE_ETHERNET is supported if the ethernet service is running.
1343 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001344 }
1345
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001346 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001347 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001348 verifyNoNetwork();
1349 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1350 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1351 assertNull(mCm.getActiveNetworkInfo());
1352 assertNull(mCm.getActiveNetwork());
1353 // Test bringing up validated cellular.
1354 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1355 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001356 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001357 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001358 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001359 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1360 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1361 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1362 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1363 // Test bringing up validated WiFi.
1364 cv = waitForConnectivityBroadcasts(2);
1365 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001366 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001367 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001368 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001369 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1370 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1371 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1372 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1373 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001374 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001375 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001376 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001377 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001378 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001379 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1380 // Test WiFi disconnect.
1381 cv = waitForConnectivityBroadcasts(1);
1382 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001383 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001384 verifyNoNetwork();
1385 }
1386
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001387 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001388 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1389 // Test bringing up unvalidated WiFi
1390 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1391 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1392 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001393 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001394 verifyActiveNetwork(TRANSPORT_WIFI);
1395 // Test bringing up unvalidated cellular
1396 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1397 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001398 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001399 verifyActiveNetwork(TRANSPORT_WIFI);
1400 // Test cellular disconnect.
1401 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001402 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001403 verifyActiveNetwork(TRANSPORT_WIFI);
1404 // Test bringing up validated cellular
1405 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1406 cv = waitForConnectivityBroadcasts(2);
1407 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001408 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001409 verifyActiveNetwork(TRANSPORT_CELLULAR);
1410 // Test cellular disconnect.
1411 cv = waitForConnectivityBroadcasts(2);
1412 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001413 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001414 verifyActiveNetwork(TRANSPORT_WIFI);
1415 // Test WiFi disconnect.
1416 cv = waitForConnectivityBroadcasts(1);
1417 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001418 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001419 verifyNoNetwork();
1420 }
1421
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001422 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001423 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1424 // Test bringing up unvalidated cellular.
1425 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1426 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1427 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001428 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001429 verifyActiveNetwork(TRANSPORT_CELLULAR);
1430 // Test bringing up unvalidated WiFi.
1431 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1432 cv = waitForConnectivityBroadcasts(2);
1433 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001434 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001435 verifyActiveNetwork(TRANSPORT_WIFI);
1436 // Test WiFi disconnect.
1437 cv = waitForConnectivityBroadcasts(2);
1438 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001439 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001440 verifyActiveNetwork(TRANSPORT_CELLULAR);
1441 // Test cellular disconnect.
1442 cv = waitForConnectivityBroadcasts(1);
1443 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001444 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001445 verifyNoNetwork();
1446 }
1447
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001448 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001449 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001450 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001451 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001452 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1453 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001454 waitFor(cv);
1455 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001456 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001457 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001458 // Test bringing up validated cellular.
1459 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001460 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001461 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001462 waitFor(cv);
1463 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001464 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1465 NET_CAPABILITY_VALIDATED));
1466 // Test cellular disconnect.
1467 cv = waitForConnectivityBroadcasts(2);
1468 mCellNetworkAgent.disconnect();
1469 waitFor(cv);
1470 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001471 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001472 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001473 NET_CAPABILITY_VALIDATED));
1474 }
1475
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001476 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001477 public void testCellularOutscoresWeakWifi() throws Exception {
1478 // Test bringing up validated cellular.
1479 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1480 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1481 mCellNetworkAgent.connect(true);
1482 waitFor(cv);
1483 verifyActiveNetwork(TRANSPORT_CELLULAR);
1484 // Test bringing up validated WiFi.
1485 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1486 cv = waitForConnectivityBroadcasts(2);
1487 mWiFiNetworkAgent.connect(true);
1488 waitFor(cv);
1489 verifyActiveNetwork(TRANSPORT_WIFI);
1490 // Test WiFi getting really weak.
1491 cv = waitForConnectivityBroadcasts(2);
1492 mWiFiNetworkAgent.adjustScore(-11);
1493 waitFor(cv);
1494 verifyActiveNetwork(TRANSPORT_CELLULAR);
1495 // Test WiFi restoring signal strength.
1496 cv = waitForConnectivityBroadcasts(2);
1497 mWiFiNetworkAgent.adjustScore(11);
1498 waitFor(cv);
1499 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001500 }
1501
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001502 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001503 public void testReapingNetwork() throws Exception {
1504 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1505 // Expect it to be torn down immediately because it satisfies no requests.
1506 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1507 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1508 mWiFiNetworkAgent.connectWithoutInternet();
1509 waitFor(cv);
1510 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1511 // Expect it to be torn down immediately because it satisfies no requests.
1512 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1513 cv = mCellNetworkAgent.getDisconnectedCV();
1514 mCellNetworkAgent.connectWithoutInternet();
1515 waitFor(cv);
1516 // Test bringing up validated WiFi.
1517 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1518 cv = waitForConnectivityBroadcasts(1);
1519 mWiFiNetworkAgent.connect(true);
1520 waitFor(cv);
1521 verifyActiveNetwork(TRANSPORT_WIFI);
1522 // Test bringing up unvalidated cellular.
1523 // Expect it to be torn down because it could never be the highest scoring network
1524 // satisfying the default request even if it validated.
1525 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1526 cv = mCellNetworkAgent.getDisconnectedCV();
1527 mCellNetworkAgent.connect(false);
1528 waitFor(cv);
1529 verifyActiveNetwork(TRANSPORT_WIFI);
1530 cv = mWiFiNetworkAgent.getDisconnectedCV();
1531 mWiFiNetworkAgent.disconnect();
1532 waitFor(cv);
1533 }
1534
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001535 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001536 public void testCellularFallback() throws Exception {
1537 // Test bringing up validated cellular.
1538 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1539 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1540 mCellNetworkAgent.connect(true);
1541 waitFor(cv);
1542 verifyActiveNetwork(TRANSPORT_CELLULAR);
1543 // Test bringing up validated WiFi.
1544 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1545 cv = waitForConnectivityBroadcasts(2);
1546 mWiFiNetworkAgent.connect(true);
1547 waitFor(cv);
1548 verifyActiveNetwork(TRANSPORT_WIFI);
1549 // Reevaluate WiFi (it'll instantly fail DNS).
1550 cv = waitForConnectivityBroadcasts(2);
1551 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1552 NET_CAPABILITY_VALIDATED));
1553 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1554 // Should quickly fall back to Cellular.
1555 waitFor(cv);
1556 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1557 NET_CAPABILITY_VALIDATED));
1558 verifyActiveNetwork(TRANSPORT_CELLULAR);
1559 // Reevaluate cellular (it'll instantly fail DNS).
1560 cv = waitForConnectivityBroadcasts(2);
1561 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1562 NET_CAPABILITY_VALIDATED));
1563 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1564 // Should quickly fall back to WiFi.
1565 waitFor(cv);
1566 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1567 NET_CAPABILITY_VALIDATED));
1568 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1569 NET_CAPABILITY_VALIDATED));
1570 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001571 }
1572
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001573 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001574 public void testWiFiFallback() throws Exception {
1575 // Test bringing up unvalidated WiFi.
1576 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1577 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1578 mWiFiNetworkAgent.connect(false);
1579 waitFor(cv);
1580 verifyActiveNetwork(TRANSPORT_WIFI);
1581 // Test bringing up validated cellular.
1582 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1583 cv = waitForConnectivityBroadcasts(2);
1584 mCellNetworkAgent.connect(true);
1585 waitFor(cv);
1586 verifyActiveNetwork(TRANSPORT_CELLULAR);
1587 // Reevaluate cellular (it'll instantly fail DNS).
1588 cv = waitForConnectivityBroadcasts(2);
1589 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1590 NET_CAPABILITY_VALIDATED));
1591 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1592 // Should quickly fall back to WiFi.
1593 waitFor(cv);
1594 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1595 NET_CAPABILITY_VALIDATED));
1596 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001597 }
1598
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001599 @Test
1600 public void testRequiresValidation() {
1601 assertTrue(NetworkMonitorUtils.isValidationRequired(
1602 mCm.getDefaultRequest().networkCapabilities));
1603 }
1604
Paul Jensen3d911462015-06-12 06:40:24 -04001605 enum CallbackState {
1606 NONE,
1607 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001608 NETWORK_CAPABILITIES,
1609 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001610 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001611 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001612 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001613 LOST,
Mike Yuf9729752018-08-17 15:22:05 +08001614 UNAVAILABLE,
1615 BLOCKED_STATUS
Paul Jensen3d911462015-06-12 06:40:24 -04001616 }
1617
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001618 private static class CallbackInfo {
1619 public final CallbackState state;
1620 public final Network network;
1621 public final Object arg;
1622 public CallbackInfo(CallbackState s, Network n, Object o) {
1623 state = s; network = n; arg = o;
1624 }
1625 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001626 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001627 }
1628 @Override
1629 public boolean equals(Object o) {
1630 if (!(o instanceof CallbackInfo)) return false;
1631 // Ignore timeMs, since it's unpredictable.
1632 CallbackInfo other = (CallbackInfo) o;
1633 return (state == other.state) && Objects.equals(network, other.network);
1634 }
1635 @Override
1636 public int hashCode() {
1637 return Objects.hash(state, network);
1638 }
1639 }
1640
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001641 /**
1642 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1643 * this class receives, by calling expectCallback() exactly once each time a callback is
1644 * received. assertNoCallback may be called at any time.
1645 */
Paul Jensen3d911462015-06-12 06:40:24 -04001646 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001647 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001648 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001649
Erik Klineacdd6392016-07-07 16:50:58 +09001650 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001651 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001652 }
Paul Jensen3d911462015-06-12 06:40:24 -04001653
Erik Klineacdd6392016-07-07 16:50:58 +09001654 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001655 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001656 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001657 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001658 }
1659
Erik Klineacdd6392016-07-07 16:50:58 +09001660 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001661 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1662 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1663 }
1664
1665 @Override
1666 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1667 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1668 }
1669
1670 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001671 public void onUnavailable() {
1672 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1673 }
1674
1675 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001676 public void onNetworkSuspended(Network network) {
1677 setLastCallback(CallbackState.SUSPENDED, network, null);
1678 }
1679
1680 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001681 public void onNetworkResumed(Network network) {
1682 setLastCallback(CallbackState.RESUMED, network, null);
1683 }
1684
1685 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001686 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001687 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001688 }
1689
Erik Klineacdd6392016-07-07 16:50:58 +09001690 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001691 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001692 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001693 setLastCallback(CallbackState.LOST, network, null);
1694 }
1695
Mike Yuf9729752018-08-17 15:22:05 +08001696 @Override
1697 public void onBlockedStatusChanged(Network network, boolean blocked) {
1698 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1699 }
1700
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001701 public Network getLastAvailableNetwork() {
1702 return mLastAvailableNetwork;
1703 }
1704
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001705 CallbackInfo nextCallback(int timeoutMs) {
1706 CallbackInfo cb = null;
1707 try {
1708 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1709 } catch (InterruptedException e) {
1710 }
1711 if (cb == null) {
1712 // LinkedBlockingQueue.poll() returns null if it timeouts.
1713 fail("Did not receive callback after " + timeoutMs + "ms");
1714 }
1715 return cb;
1716 }
1717
Erik Kline1d3db322017-02-28 16:20:20 +09001718 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1719 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1720 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001721 CallbackInfo actual = nextCallback(timeoutMs);
1722 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001723
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001724 if (state == CallbackState.LOSING) {
1725 String msg = String.format(
1726 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001727 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001728 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001729 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001730 }
Erik Kline1d3db322017-02-28 16:20:20 +09001731
1732 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001733 }
1734
Erik Kline1d3db322017-02-28 16:20:20 +09001735 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001736 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001737 }
1738
Hugo Benichi16f0a942017-06-20 14:07:59 +09001739 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001740 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09001741 }
1742
1743 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1744 int timeLeft = timeoutMs;
1745 while (timeLeft > 0) {
1746 long start = SystemClock.elapsedRealtime();
1747 CallbackInfo info = nextCallback(timeLeft);
1748 if (fn.test(info)) {
1749 return info;
1750 }
1751 timeLeft -= (SystemClock.elapsedRealtime() - start);
1752 }
1753 fail("Did not receive expected callback after " + timeoutMs + "ms");
1754 return null;
1755 }
1756
Lorenzo Colitti27334542018-01-12 16:22:21 +09001757 // Expects onAvailable and the callbacks that follow it. These are:
1758 // - onSuspended, iff the network was suspended when the callbacks fire.
1759 // - onCapabilitiesChanged.
1760 // - onLinkPropertiesChanged.
Mike Yuf9729752018-08-17 15:22:05 +08001761 // - onBlockedStatusChanged.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001762 //
1763 // @param agent the network to expect the callbacks on.
1764 // @param expectSuspended whether to expect a SUSPENDED callback.
1765 // @param expectValidated the expected value of the VALIDATED capability in the
1766 // onCapabilitiesChanged callback.
1767 // @param timeoutMs how long to wait for the callbacks.
1768 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
Mike Yuf9729752018-08-17 15:22:05 +08001769 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001770 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001771 if (expectSuspended) {
1772 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001773 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001774 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001775 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001776 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001777 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001778 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001779 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Mike Yuf9729752018-08-17 15:22:05 +08001780 expectBlockedStatusCallback(expectBlocked, agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001781 }
1782
Lorenzo Colitti27334542018-01-12 16:22:21 +09001783 // Expects the available callbacks (validated), plus onSuspended.
1784 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
Mike Yuf9729752018-08-17 15:22:05 +08001785 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001786 }
1787
Lorenzo Colitti27334542018-01-12 16:22:21 +09001788 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001789 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1790 }
1791
1792 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1793 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001794 }
1795
Lorenzo Colitti27334542018-01-12 16:22:21 +09001796 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001797 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1798 }
1799
1800 void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1801 expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001802 }
1803
1804 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1805 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1806 // one we just sent.
1807 // TODO: this is likely a bug. Fix it and remove this method.
1808 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001809 expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001810 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001811 expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
Mike Yuf9729752018-08-17 15:22:05 +08001812 // Implicitly check the network is allowed to use.
1813 // TODO: should we need to consider if network is in blocked status in this case?
1814 expectBlockedStatusCallback(false, agent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001815 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1816 assertEquals(nc1, nc2);
1817 }
1818
1819 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1820 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1821 // when a network connects and satisfies a callback, and then immediately validates.
1822 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1823 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001824 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1825 }
1826
Lorenzo Colitti27334542018-01-12 16:22:21 +09001827 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001828 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001829 }
1830
1831 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1832 int timeoutMs) {
1833 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001834 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1835 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001836 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001837 }
1838
Lorenzo Colitti27334542018-01-12 16:22:21 +09001839 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001840 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001841 }
1842
1843 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1844 int timeoutMs) {
1845 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001846 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1847 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001848 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001849 }
1850
Chalard Jean0b214af2018-01-12 17:22:49 +09001851 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1852 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001853 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1854 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001855 }
1856
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09001857 void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1858 CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1859 assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1860 fn.test((LinkProperties) cbi.arg));
1861 }
1862
Mike Yuf9729752018-08-17 15:22:05 +08001863 void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1864 CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1865 boolean actualBlocked = (boolean) cbi.arg;
1866 assertEquals(expectBlocked, actualBlocked);
1867 }
1868
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001869 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001870 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001871 CallbackInfo c = mCallbacks.peek();
1872 assertNull("Unexpected callback: " + c, c);
1873 }
1874 }
1875
1876 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1877 // only be declared in a static or top level type".
1878 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1879 for (TestNetworkCallback c : callbacks) {
1880 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001881 }
1882 }
1883
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001884 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001885 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001886 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001887 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1888 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001889 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1890 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001891 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1892 .addTransportType(TRANSPORT_WIFI).build();
1893 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1894 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001895 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001896 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1897 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1898
1899 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001900 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1901 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1902 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001903 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1904 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001905 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1906 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001907 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001908
Paul Jensen3d911462015-06-12 06:40:24 -04001909 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1910 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001911 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001912 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001913 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1914
Paul Jensen3d911462015-06-12 06:40:24 -04001915 cv = waitForConnectivityBroadcasts(2);
1916 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1917 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001918 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1919 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001920 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1921 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001922 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001923
Paul Jensen3d911462015-06-12 06:40:24 -04001924 cv = waitForConnectivityBroadcasts(2);
1925 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001926 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1927 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001928 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001929 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001930 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001931
Paul Jensen3d911462015-06-12 06:40:24 -04001932 cv = waitForConnectivityBroadcasts(1);
1933 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001934 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1935 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001936 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001937 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001938
1939 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001940 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1941 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001942 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1943 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001944 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001945 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001946
Paul Jensen3d911462015-06-12 06:40:24 -04001947 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1948 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001949 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001950 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001951 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1952
Paul Jensen3d911462015-06-12 06:40:24 -04001953 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1954 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001955 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001956 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001957 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001958 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001959 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001960 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001961 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001962
Paul Jensen3d911462015-06-12 06:40:24 -04001963 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001964 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1965 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1966 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001967
Paul Jensen3d911462015-06-12 06:40:24 -04001968 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001969 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1970 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1971 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001972 }
1973
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001974 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001975 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001976 // This test would be flaky with the default 120ms timer: that is short enough that
1977 // lingered networks are torn down before assertions can be run. We don't want to mock the
1978 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1979 // in detecting races.
1980 mService.mLingerDelayMs = 300;
1981
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001982 NetworkRequest request = new NetworkRequest.Builder()
1983 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1984 .build();
1985 TestNetworkCallback callback = new TestNetworkCallback();
1986 mCm.registerNetworkCallback(request, callback);
1987
1988 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1989 mCm.registerDefaultNetworkCallback(defaultCallback);
1990
1991 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1992 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1993 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1994
1995 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1996 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1997 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1998
1999 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002000 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2001 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002002 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002003 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002004
2005 mWiFiNetworkAgent.connect(true);
2006 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
2007 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002008 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002009 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002010 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002011 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002012 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002013 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002014 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002015
2016 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002017 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002018 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002019 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002020 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002021 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002022 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002023 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002024
2025 mEthernetNetworkAgent.disconnect();
2026 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2027 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002028 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002029 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002030
2031 for (int i = 0; i < 4; i++) {
2032 MockNetworkAgent oldNetwork, newNetwork;
2033 if (i % 2 == 0) {
2034 mWiFiNetworkAgent.adjustScore(-15);
2035 oldNetwork = mWiFiNetworkAgent;
2036 newNetwork = mCellNetworkAgent;
2037 } else {
2038 mWiFiNetworkAgent.adjustScore(15);
2039 oldNetwork = mCellNetworkAgent;
2040 newNetwork = mWiFiNetworkAgent;
2041
2042 }
2043 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002044 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2045 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002046 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002047 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2048 }
2049 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2050
2051 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2052 // if the network is still up.
2053 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002054 // We expect a notification about the capabilities change, and nothing else.
2055 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2056 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002057 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002058 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002059
2060 // Wifi no longer satisfies our listen, which is for an unmetered network.
2061 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002062 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2063
2064 // Disconnect our test networks.
2065 mWiFiNetworkAgent.disconnect();
2066 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002067 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002068 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002069 mCellNetworkAgent.disconnect();
2070 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002071 waitForIdle();
2072 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002073
2074 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002075 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002076
2077 // Check that a network is only lingered or torn down if it would not satisfy a request even
2078 // if it validated.
2079 request = new NetworkRequest.Builder().clearCapabilities().build();
2080 callback = new TestNetworkCallback();
2081
2082 mCm.registerNetworkCallback(request, callback);
2083
2084 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2085 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002086 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2087 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002088 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002089 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002090
2091 // Bring up wifi with a score of 20.
2092 // Cell stays up because it would satisfy the default request if it validated.
2093 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2094 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002095 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2096 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002097 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002098 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002099
2100 mWiFiNetworkAgent.disconnect();
2101 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2102 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002103 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002104 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002105 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002106
2107 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002108 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002109 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2110 mWiFiNetworkAgent.adjustScore(50);
2111 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002112 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002113 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002114 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002115 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002116 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002117
2118 // Tear down wifi.
2119 mWiFiNetworkAgent.disconnect();
2120 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2121 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002122 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002123 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002124 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002125
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002126 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2127 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002128 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2129 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002130 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002131 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002132 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002133 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002134 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002135 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002136 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002137
2138 mWiFiNetworkAgent.disconnect();
2139 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002140 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002141 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002142 mCellNetworkAgent.disconnect();
2143 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2144 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002145 waitForIdle();
2146 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002147
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002148 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002149 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2150 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002151 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2152 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002153 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002154 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2155 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002156 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2157 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002158 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002159 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002160 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002161 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002162
2163 NetworkRequest cellRequest = new NetworkRequest.Builder()
2164 .addTransportType(TRANSPORT_CELLULAR).build();
2165 NetworkCallback noopCallback = new NetworkCallback();
2166 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002167 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2168 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002169 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002170 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002171
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002172 // Similar to the above: lingering can start even after the lingered request is removed.
2173 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002174 mWiFiNetworkAgent.disconnect();
2175 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002176 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002177 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002178 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002179
2180 // Cell is now the default network. Pin it with a cell-specific request.
2181 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2182 mCm.requestNetwork(cellRequest, noopCallback);
2183
2184 // Now connect wifi, and expect it to become the default network.
2185 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2186 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002187 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2188 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002189 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002190 // The default request is lingering on cell, but nothing happens to cell, and we send no
2191 // callbacks for it, because it's kept up by cellRequest.
2192 callback.assertNoCallback();
2193 // Now unregister cellRequest and expect cell to start lingering.
2194 mCm.unregisterNetworkCallback(noopCallback);
2195 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2196
2197 // Let linger run its course.
2198 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002199 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002200 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002201
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002202 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2203 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2204 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002205 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002206 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2207 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002208 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002209 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2210 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002211 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2212 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002213 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002214
2215 // Let linger run its course.
2216 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2217
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002218 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002219 mEthernetNetworkAgent.disconnect();
2220 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2221 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2222 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002223
2224 mCm.unregisterNetworkCallback(callback);
2225 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002226 mCm.unregisterNetworkCallback(trackDefaultCallback);
2227 }
2228
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002229 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002230 public void testNetworkGoesIntoBackgroundAfterLinger() {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002231 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002232 NetworkRequest request = new NetworkRequest.Builder()
2233 .clearCapabilities()
2234 .build();
2235 TestNetworkCallback callback = new TestNetworkCallback();
2236 mCm.registerNetworkCallback(request, callback);
2237
2238 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2239 mCm.registerDefaultNetworkCallback(defaultCallback);
2240
2241 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2242 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2243
2244 mCellNetworkAgent.connect(true);
2245 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2246 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2247
2248 // Wifi comes up and cell lingers.
2249 mWiFiNetworkAgent.connect(true);
2250 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2251 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2252 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2253 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2254
2255 // File a request for cellular, then release it.
2256 NetworkRequest cellRequest = new NetworkRequest.Builder()
2257 .addTransportType(TRANSPORT_CELLULAR).build();
2258 NetworkCallback noopCallback = new NetworkCallback();
2259 mCm.requestNetwork(cellRequest, noopCallback);
2260 mCm.unregisterNetworkCallback(noopCallback);
2261 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2262
2263 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002264 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002265 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2266 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2267 lingerTimeoutMs);
2268
2269 // Clean up.
2270 mCm.unregisterNetworkCallback(defaultCallback);
2271 mCm.unregisterNetworkCallback(callback);
2272 }
2273
2274 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002275 public void testExplicitlySelected() {
2276 NetworkRequest request = new NetworkRequest.Builder()
2277 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2278 .build();
2279 TestNetworkCallback callback = new TestNetworkCallback();
2280 mCm.registerNetworkCallback(request, callback);
2281
2282 // Bring up validated cell.
2283 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2284 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002285 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002286
2287 // Bring up unvalidated wifi with explicitlySelected=true.
2288 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2289 mWiFiNetworkAgent.explicitlySelected(false);
2290 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002291 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002292
2293 // Cell Remains the default.
2294 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2295
2296 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2297 // it's explicitly selected.
2298 mWiFiNetworkAgent.adjustScore(-40);
2299 mWiFiNetworkAgent.adjustScore(40);
2300 callback.assertNoCallback();
2301
2302 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2303 // wifi even though it's unvalidated.
2304 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2305 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2306 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2307
2308 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2309 mWiFiNetworkAgent.disconnect();
2310 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2311 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2312 mWiFiNetworkAgent.explicitlySelected(false);
2313 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002314 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002315
2316 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2317 // network to disconnect.
2318 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2319 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2320
2321 // Reconnect, again with explicitlySelected=true, but this time validate.
2322 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2323 mWiFiNetworkAgent.explicitlySelected(false);
2324 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002325 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002326 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2327 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2328 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2329
2330 // BUG: the network will no longer linger, even though it's validated and outscored.
2331 // TODO: fix this.
2332 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2333 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002334 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002335 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2336 callback.assertNoCallback();
2337
2338 // Clean up.
2339 mWiFiNetworkAgent.disconnect();
2340 mCellNetworkAgent.disconnect();
2341 mEthernetNetworkAgent.disconnect();
2342
2343 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2344 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2345 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002346 }
2347
Chalard Jean08577fc2018-05-02 21:14:54 +09002348 private int[] makeIntArray(final int size, final int value) {
2349 final int[] array = new int[size];
2350 Arrays.fill(array, value);
2351 return array;
2352 }
2353
Paul Jensen85cf78e2015-06-25 13:25:07 -04002354 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002355 // Verify NOT_RESTRICTED is set appropriately
2356 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2357 .build().networkCapabilities;
2358 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2359 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2360 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002361 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002362 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2363 } else {
2364 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2365 }
2366
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002367 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002368 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002369 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2370 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002371 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002372 mServiceContext, "testFactory", filter);
2373 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002374 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean08577fc2018-05-02 21:14:54 +09002375 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002376 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002377 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002378 int expectedRequestCount = 1;
2379 NetworkCallback networkCallback = null;
2380 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2381 // add one.
2382 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002383 assertFalse(testFactory.getMyStartRequested());
2384 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2385 networkCallback = new NetworkCallback();
Chalard Jean08577fc2018-05-02 21:14:54 +09002386 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002387 mCm.requestNetwork(request, networkCallback);
2388 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002389 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002390 }
Paul Jensen3d911462015-06-12 06:40:24 -04002391 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002392 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2393 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002394
Paul Jensen85cf78e2015-06-25 13:25:07 -04002395 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002396 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002397 // Rather than create a validated network which complicates things by registering it's
2398 // own NetworkRequest during startup, just bump up the score to cancel out the
2399 // unvalidated penalty.
2400 testAgent.adjustScore(40);
2401 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002402
2403 // When testAgent connects, ConnectivityService will re-send us all current requests with
2404 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2405 // them.
Chalard Jean08577fc2018-05-02 21:14:54 +09002406 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002407 testAgent.connect(false);
2408 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002409 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002410 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002411 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002412
Paul Jensen85cf78e2015-06-25 13:25:07 -04002413 // Bring in a bunch of requests.
Chalard Jean08577fc2018-05-02 21:14:54 +09002414 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002415 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002416 ConnectivityManager.NetworkCallback[] networkCallbacks =
2417 new ConnectivityManager.NetworkCallback[10];
2418 for (int i = 0; i< networkCallbacks.length; i++) {
2419 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2420 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002421 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002422 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2423 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002424 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2425 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002426
Paul Jensen85cf78e2015-06-25 13:25:07 -04002427 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002428 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002429 for (int i = 0; i < networkCallbacks.length; i++) {
2430 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2431 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002432 testFactory.waitForNetworkRequests(expectedRequestCount);
2433 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002434
Paul Jensen85cf78e2015-06-25 13:25:07 -04002435 // Drop the higher scored network.
2436 cv = testFactory.getNetworkStartedCV();
Chalard Jean08577fc2018-05-02 21:14:54 +09002437 // With the default network disconnecting, the requests are sent with score 0 to factories.
2438 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002439 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002440 waitFor(cv);
Chalard Jean08577fc2018-05-02 21:14:54 +09002441 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002442 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2443 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002444
2445 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002446 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002447 handlerThread.quit();
2448 }
2449
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002450 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002451 public void testNetworkFactoryRequests() throws Exception {
2452 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2453 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2454 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2455 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2456 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2457 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2458 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2459 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2460 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2461 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2462 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2463 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2464 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2465 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2466 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2467 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2468 }
2469
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002470 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002471 public void testNoMutableNetworkRequests() throws Exception {
2472 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002473 NetworkRequest request1 = new NetworkRequest.Builder()
2474 .addCapability(NET_CAPABILITY_VALIDATED)
2475 .build();
2476 NetworkRequest request2 = new NetworkRequest.Builder()
2477 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2478 .build();
2479
2480 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2481 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2482 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2483 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2484 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002485 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002486
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002487 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002488 public void testMMSonWiFi() throws Exception {
2489 // Test bringing up cellular without MMS NetworkRequest gets reaped
2490 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2491 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2492 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2493 mCellNetworkAgent.connectWithoutInternet();
2494 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002495 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002496 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002497 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002498
Paul Jensene0988542015-06-25 15:30:08 -04002499 // Test bringing up validated WiFi.
2500 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2501 cv = waitForConnectivityBroadcasts(1);
2502 mWiFiNetworkAgent.connect(true);
2503 waitFor(cv);
2504 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002505
Paul Jensene0988542015-06-25 15:30:08 -04002506 // Register MMS NetworkRequest
2507 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2508 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2509 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2510 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002511
Paul Jensene0988542015-06-25 15:30:08 -04002512 // Test bringing up unvalidated cellular with MMS
2513 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2514 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002515 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002516 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002517 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002518
Paul Jensene0988542015-06-25 15:30:08 -04002519 // Test releasing NetworkRequest disconnects cellular with MMS
2520 cv = mCellNetworkAgent.getDisconnectedCV();
2521 mCm.unregisterNetworkCallback(networkCallback);
2522 waitFor(cv);
2523 verifyActiveNetwork(TRANSPORT_WIFI);
2524 }
2525
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002526 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002527 public void testMMSonCell() throws Exception {
2528 // Test bringing up cellular without MMS
2529 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2530 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2531 mCellNetworkAgent.connect(false);
2532 waitFor(cv);
2533 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002534
Paul Jensene0988542015-06-25 15:30:08 -04002535 // Register MMS NetworkRequest
2536 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2537 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2538 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2539 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002540
Paul Jensene0988542015-06-25 15:30:08 -04002541 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002542 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2543 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2544 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002545 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002546 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002547
Paul Jensene0988542015-06-25 15:30:08 -04002548 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2549 cv = mmsNetworkAgent.getDisconnectedCV();
2550 mCm.unregisterNetworkCallback(networkCallback);
2551 waitFor(cv);
2552 verifyActiveNetwork(TRANSPORT_CELLULAR);
2553 }
2554
lucaslinf3b59b32019-03-26 17:49:49 +08002555 @Test
lucasline252a742019-03-12 13:08:03 +08002556 public void testPartialConnectivity() {
2557 // Register network callback.
2558 NetworkRequest request = new NetworkRequest.Builder()
2559 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2560 .build();
2561 TestNetworkCallback callback = new TestNetworkCallback();
2562 mCm.registerNetworkCallback(request, callback);
2563
2564 // Bring up validated mobile data.
2565 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2566 mCellNetworkAgent.connect(true);
2567 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2568
2569 // Bring up wifi with partial connectivity.
2570 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2571 mWiFiNetworkAgent.connectWithPartialConnectivity();
2572 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2573 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2574
2575 // Mobile data should be the default network.
2576 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2577 callback.assertNoCallback();
2578
lucaslinf3b59b32019-03-26 17:49:49 +08002579 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2580 // probe.
2581 mWiFiNetworkAgent.setNetworkValid();
lucasline252a742019-03-12 13:08:03 +08002582 // If the user chooses yes to use this partial connectivity wifi, switch the default
2583 // network to wifi and check if wifi becomes valid or not.
2584 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2585 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002586 // If user accepts partial connectivity network,
2587 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002588 waitForIdle();
2589 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002590 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002591 } catch (RemoteException e) {
2592 fail(e.getMessage());
2593 }
lucaslinf3b59b32019-03-26 17:49:49 +08002594 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2595 // validated.
2596 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
lucasline252a742019-03-12 13:08:03 +08002597 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2598 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2599 mWiFiNetworkAgent);
2600 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2601 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2602
2603 // Disconnect and reconnect wifi with partial connectivity again.
2604 mWiFiNetworkAgent.disconnect();
2605 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2606 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2607 mWiFiNetworkAgent.connectWithPartialConnectivity();
2608 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2609 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2610
2611 // Mobile data should be the default network.
2612 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2613
2614 // If the user chooses no, disconnect wifi immediately.
2615 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2616 false /* always */);
2617 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2618
2619 // If user accepted partial connectivity before, and device reconnects to that network
2620 // again, but now the network has full connectivity. The network shouldn't contain
2621 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2622 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2623 // acceptUnvalidated is also used as setting for accepting partial networks.
2624 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
2625 mWiFiNetworkAgent.connect(true);
lucaslinf3b59b32019-03-26 17:49:49 +08002626 // If user accepted partial connectivity network before,
2627 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2628 // ConnectivityService#updateNetworkInfo().
2629 waitForIdle();
2630 try {
2631 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2632 } catch (RemoteException e) {
2633 fail(e.getMessage());
2634 }
lucasline252a742019-03-12 13:08:03 +08002635 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2636 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2637 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2638 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2639 // Wifi should be the default network.
2640 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2641 mWiFiNetworkAgent.disconnect();
2642 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2643
2644 // If user accepted partial connectivity before, and now the device reconnects to the
2645 // partial connectivity network. The network should be valid and contain
2646 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2647 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2648 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
lucaslinf3b59b32019-03-26 17:49:49 +08002649 // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
2650 // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
2651 // to ConnectivityService first then send VALID. Once NetworkMonitor support
2652 // multi-testResult, this test case also need to be changed to meet the new design.
lucasline252a742019-03-12 13:08:03 +08002653 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002654 // If user accepted partial connectivity network before,
2655 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2656 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002657 waitForIdle();
2658 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002659 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002660 } catch (RemoteException e) {
2661 fail(e.getMessage());
2662 }
lucaslinf3b59b32019-03-26 17:49:49 +08002663 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002664 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
lucaslinf3b59b32019-03-26 17:49:49 +08002665 // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
2666 // NetworkMonitor detects partial connectivity
lucasline252a742019-03-12 13:08:03 +08002667 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002668 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2669 mWiFiNetworkAgent.setNetworkValid();
2670 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2671 // validated.
2672 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2673 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2674 mWiFiNetworkAgent.disconnect();
2675 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002676 }
2677
2678 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002679 public void testCaptivePortal() {
2680 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2681 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2682 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2683 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2684
2685 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2686 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2687 .addCapability(NET_CAPABILITY_VALIDATED).build();
2688 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002689
2690 // Bring up a network with a captive portal.
2691 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002692 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002693 String firstRedirectUrl = "http://example.com/firstPath";
2694 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002695 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002696 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002697
2698 // Take down network.
2699 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002700 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002701 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002702
2703 // Bring up a network with a captive portal.
2704 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002705 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002706 String secondRedirectUrl = "http://example.com/secondPath";
2707 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002708 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002709 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002710
2711 // Make captive portal disappear then revalidate.
2712 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002713 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002714 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002715 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002716
2717 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002718 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002719
2720 // Break network connectivity.
2721 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002722 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002723 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002724 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002725 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002726
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002727 @Test
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002728 public void testCaptivePortalApp() throws RemoteException {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002729 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2730 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2731 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2732 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2733
2734 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2735 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2736 .addCapability(NET_CAPABILITY_VALIDATED).build();
2737 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2738
2739 // Bring up wifi.
2740 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2741 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002742 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002743 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2744
2745 // Check that calling startCaptivePortalApp does nothing.
2746 final int fastTimeoutMs = 100;
2747 mCm.startCaptivePortalApp(wifiNetwork);
2748 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2749
2750 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002751 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002752 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002753 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002754 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2755
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002756 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002757 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002758 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2759 .launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002760
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002761 // Report that the captive portal is dismissed, and check that callbacks are fired
2762 mWiFiNetworkAgent.setNetworkValid();
2763 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002764 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002765 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2766
2767 mCm.unregisterNetworkCallback(validatedCallback);
2768 mCm.unregisterNetworkCallback(captivePortalCallback);
2769 }
2770
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002771 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002772 public void testAvoidOrIgnoreCaptivePortals() {
2773 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2774 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2775 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2776 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2777
2778 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2779 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2780 .addCapability(NET_CAPABILITY_VALIDATED).build();
2781 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2782
2783 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2784 // Bring up a network with a captive portal.
2785 // Expect it to fail to connect and not result in any callbacks.
2786 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2787 String firstRedirectUrl = "http://example.com/firstPath";
2788
2789 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2790 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2791 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2792 waitFor(disconnectCv);
2793 waitFor(avoidCv);
2794
2795 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002796 }
2797
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002798 private NetworkRequest.Builder newWifiRequestBuilder() {
2799 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2800 }
2801
Etan Cohen836ad572018-12-30 17:59:59 -08002802 /**
2803 * Verify request matching behavior with network specifiers.
2804 *
2805 * Note: this test is somewhat problematic since it involves removing capabilities from
2806 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2807 * as a WTF bug in
2808 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2809 * does work.
2810 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002811 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002812 public void testNetworkSpecifier() {
Etan Cohen836ad572018-12-30 17:59:59 -08002813 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2814 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2815 Parcelable {
2816 @Override
2817 public boolean satisfiedBy(NetworkSpecifier other) {
2818 return true;
2819 }
2820
2821 @Override
2822 public int describeContents() {
2823 return 0;
2824 }
2825
2826 @Override
2827 public void writeToParcel(Parcel dest, int flags) {}
2828
2829 @Override
2830 public NetworkSpecifier redact() {
2831 return null;
2832 }
2833 }
2834
2835 // A network specifier that matches either another LocalNetworkSpecifier with the same
2836 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2837 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2838 private String mString;
2839
2840 LocalStringNetworkSpecifier(String string) {
2841 mString = string;
2842 }
2843
2844 @Override
2845 public boolean satisfiedBy(NetworkSpecifier other) {
2846 if (other instanceof LocalStringNetworkSpecifier) {
2847 return TextUtils.equals(mString,
2848 ((LocalStringNetworkSpecifier) other).mString);
2849 }
2850 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2851 return false;
2852 }
2853
2854 @Override
2855 public int describeContents() {
2856 return 0;
2857 }
2858 @Override
2859 public void writeToParcel(Parcel dest, int flags) {}
2860 }
2861
2862
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002863 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002864 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002865 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002866 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2867 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002868 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2869 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002870 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002871 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002872
2873 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2874 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2875 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002876 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002877 TestNetworkCallback cFoo = new TestNetworkCallback();
2878 TestNetworkCallback cBar = new TestNetworkCallback();
2879 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002880 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002881
2882 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2883 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2884 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002885 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002886 mCm.registerNetworkCallback(rFoo, cFoo);
2887 mCm.registerNetworkCallback(rBar, cBar);
2888
Etan Cohen836ad572018-12-30 17:59:59 -08002889 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2890 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2891
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002892 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2893 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002894 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2895 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2896 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2897 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002898 assertNoCallbacks(cFoo, cBar);
2899
Etan Cohen836ad572018-12-30 17:59:59 -08002900 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002901 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002902 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002903 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2904 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002905 }
Etan Cohen836ad572018-12-30 17:59:59 -08002906 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2907 mWiFiNetworkAgent);
2908 assertEquals(nsFoo,
2909 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002910 cFoo.assertNoCallback();
2911
Etan Cohen836ad572018-12-30 17:59:59 -08002912 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002913 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002914 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002915 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002916 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2917 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002918 }
Etan Cohen836ad572018-12-30 17:59:59 -08002919 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2920 mWiFiNetworkAgent);
2921 assertEquals(nsBar,
2922 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2923 cBar.assertNoCallback();
2924
2925 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2926 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2927 for (TestNetworkCallback c : emptyCallbacks) {
2928 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2929 mWiFiNetworkAgent);
2930 }
2931 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2932 mWiFiNetworkAgent);
2933 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2934 mWiFiNetworkAgent);
2935 assertNull(
2936 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2937 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002938 cBar.assertNoCallback();
2939
2940 mWiFiNetworkAgent.setNetworkSpecifier(null);
Etan Cohen836ad572018-12-30 17:59:59 -08002941 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002942 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2943 for (TestNetworkCallback c: emptyCallbacks) {
2944 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2945 }
2946
Etan Cohen836ad572018-12-30 17:59:59 -08002947 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002948 }
2949
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002950 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002951 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002952 try {
2953 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002954 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
2955 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
2956 } catch (IllegalArgumentException expected) {
2957 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002958 }
2959
Etan Cohenddb9ef02015-11-18 10:56:15 -08002960 try {
2961 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2962 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002963 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002964 mService.requestNetwork(networkCapabilities, null, 0, null,
2965 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07002966 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
2967 } catch (IllegalArgumentException expected) {
2968 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002969 }
2970
Etan Cohena7434272017-04-03 12:17:51 -07002971 class NonParcelableSpecifier extends NetworkSpecifier {
2972 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2973 };
2974 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2975 @Override public int describeContents() { return 0; }
2976 @Override public void writeToParcel(Parcel p, int flags) {}
2977 }
2978 NetworkRequest.Builder builder;
2979
2980 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2981 try {
2982 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2983 Parcel parcelW = Parcel.obtain();
2984 builder.build().writeToParcel(parcelW, 0);
2985 fail("Parceling a non-parcelable specifier did not throw an exception");
2986 } catch (Exception e) {
2987 // expected
2988 }
2989
2990 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2991 builder.setNetworkSpecifier(new ParcelableSpecifier());
2992 NetworkRequest nr = builder.build();
2993 assertNotNull(nr);
2994
2995 try {
2996 Parcel parcelW = Parcel.obtain();
2997 nr.writeToParcel(parcelW, 0);
2998 byte[] bytes = parcelW.marshall();
2999 parcelW.recycle();
3000
3001 Parcel parcelR = Parcel.obtain();
3002 parcelR.unmarshall(bytes, 0, bytes.length);
3003 parcelR.setDataPosition(0);
3004 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
3005 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
3006 } catch (Exception e) {
3007 // expected
3008 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08003009 }
3010
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003011 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07003012 public void testNetworkSpecifierUidSpoofSecurityException() {
3013 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3014 @Override
3015 public boolean satisfiedBy(NetworkSpecifier other) {
3016 return true;
3017 }
3018
3019 @Override
3020 public void assertValidFromUid(int requestorUid) {
3021 throw new SecurityException("failure");
3022 }
3023
3024 @Override
3025 public int describeContents() { return 0; }
3026 @Override
3027 public void writeToParcel(Parcel dest, int flags) {}
3028 }
3029
3030 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3031 mWiFiNetworkAgent.connect(false);
3032
3033 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
3034 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
3035 networkSpecifier).build();
3036 TestNetworkCallback networkCallback = new TestNetworkCallback();
3037 try {
3038 mCm.requestNetwork(networkRequest, networkCallback);
3039 fail("Network request with spoofed UID did not throw a SecurityException");
3040 } catch (SecurityException e) {
3041 // expected
3042 }
3043 }
3044
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003045 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003046 public void testRegisterDefaultNetworkCallback() throws Exception {
3047 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3048 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3049 defaultNetworkCallback.assertNoCallback();
3050
3051 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3052 // whenever Wi-Fi is up. Without this, the mobile network agent is
3053 // reaped before any other activity can take place.
3054 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3055 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3056 .addTransportType(TRANSPORT_CELLULAR).build();
3057 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3058 cellNetworkCallback.assertNoCallback();
3059
3060 // Bring up cell and expect CALLBACK_AVAILABLE.
3061 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3062 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003063 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3064 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003065 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003066
3067 // Bring up wifi and expect CALLBACK_AVAILABLE.
3068 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3069 mWiFiNetworkAgent.connect(true);
3070 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003071 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003072 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003073
3074 // Bring down cell. Expect no default network callback, since it wasn't the default.
3075 mCellNetworkAgent.disconnect();
3076 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3077 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003078 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003079
3080 // Bring up cell. Expect no default network callback, since it won't be the default.
3081 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3082 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003083 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003084 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003085 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003086
3087 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3088 // followed by AVAILABLE cell.
3089 mWiFiNetworkAgent.disconnect();
3090 cellNetworkCallback.assertNoCallback();
3091 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003092 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003093 mCellNetworkAgent.disconnect();
3094 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3095 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003096 waitForIdle();
3097 assertEquals(null, mCm.getActiveNetwork());
3098
3099 final int uid = Process.myUid();
3100 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
3101 final ArraySet<UidRange> ranges = new ArraySet<>();
3102 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003103 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3104 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003105 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003106 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003107 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3108 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3109
3110 vpnNetworkAgent.disconnect();
3111 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3112 waitForIdle();
3113 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003114 }
3115
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003116 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003117 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003118 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003119 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003120 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3121 .addTransportType(TRANSPORT_CELLULAR).build();
3122 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3123
3124 // Bring up the mobile network.
3125 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3126 mCellNetworkAgent.connect(true);
3127
Erik Kline1d3db322017-02-28 16:20:20 +09003128 // We should get onAvailable(), onCapabilitiesChanged(), and
3129 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3130 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003131 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003132 cellNetworkCallback.assertNoCallback();
3133
3134 // Update LinkProperties.
3135 final LinkProperties lp = new LinkProperties();
3136 lp.setInterfaceName("foonet_data0");
3137 mCellNetworkAgent.sendLinkProperties(lp);
3138 // We should get onLinkPropertiesChanged().
3139 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
3140 cellNetworkCallback.assertNoCallback();
3141
Erik Kline1d3db322017-02-28 16:20:20 +09003142 // Suspend the network.
3143 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003144 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3145 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003146 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
3147 cellNetworkCallback.assertNoCallback();
3148
Erik Klineacdd6392016-07-07 16:50:58 +09003149 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003150 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003151 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003152 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3153 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003154 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003155 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003156 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3157
3158 mCellNetworkAgent.resume();
3159 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3160 mCellNetworkAgent);
3161 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
3162 cellNetworkCallback.assertNoCallback();
3163
3164 dfltNetworkCallback = new TestNetworkCallback();
3165 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3166 // This time onNetworkSuspended should not be called.
3167 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3168 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003169
Erik Klineacdd6392016-07-07 16:50:58 +09003170 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3171 mCm.unregisterNetworkCallback(cellNetworkCallback);
3172 }
3173
Calvin On1f64f3f2016-10-11 15:10:46 -07003174 private void setCaptivePortalMode(int mode) {
3175 ContentResolver cr = mServiceContext.getContentResolver();
3176 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3177 }
3178
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003179 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003180 ContentResolver cr = mServiceContext.getContentResolver();
3181 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003182 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003183 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003184 }
3185
Erik Kline79c6d052018-03-21 07:18:33 -07003186 private void setPrivateDnsSettings(String mode, String specifier) {
3187 final ContentResolver cr = mServiceContext.getContentResolver();
3188 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3189 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3190 mService.updatePrivateDnsSettings();
3191 waitForIdle();
3192 }
3193
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003194 private boolean isForegroundNetwork(MockNetworkAgent network) {
3195 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3196 assertNotNull(nc);
3197 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3198 }
3199
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003200 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003201 public void testBackgroundNetworks() throws Exception {
3202 // Create a background request. We can't do this ourselves because ConnectivityService
3203 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003204 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003205 final NetworkRequest request = new NetworkRequest.Builder().build();
3206 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3207 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3208 final TestNetworkCallback callback = new TestNetworkCallback();
3209 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3210 mCm.registerNetworkCallback(request, callback);
3211 mCm.registerNetworkCallback(fgRequest, fgCallback);
3212
3213 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3214 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003215 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3216 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003217 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3218
3219 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3220 mWiFiNetworkAgent.connect(true);
3221
3222 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003223 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003224 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003225 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003226 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003227 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003228 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003229 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3230 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3231
3232 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003233 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003234 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3235 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003236 // Expect a network capabilities update sans FOREGROUND.
3237 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003238 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3239 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3240
3241 // File a cell request and check that cell comes into the foreground.
3242 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3243 .addTransportType(TRANSPORT_CELLULAR).build();
3244 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3245 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003246 // NOTE: This request causes the network's capabilities to change. This
3247 // is currently delivered before the onAvailable() callbacks.
3248 // TODO: Fix this.
3249 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003250 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3251 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003252 // Expect a network capabilities update with FOREGROUND, because the most recent
3253 // request causes its state to change.
3254 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003255 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3256 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3257
3258 // Release the request. The network immediately goes into the background, since it was not
3259 // lingering.
3260 mCm.unregisterNetworkCallback(cellCallback);
3261 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003262 // Expect a network capabilities update sans FOREGROUND.
3263 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003264 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3265 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3266
3267 // Disconnect wifi and check that cell is foreground again.
3268 mWiFiNetworkAgent.disconnect();
3269 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3270 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003271 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003272 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3273
3274 mCm.unregisterNetworkCallback(callback);
3275 mCm.unregisterNetworkCallback(fgCallback);
3276 }
3277
Hugo Benichi849b81b2017-05-25 13:42:31 +09003278 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003279 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003280 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003281 // Benchmarks connecting and switching performance in the presence of a large number of
3282 // NetworkRequests.
3283 // 1. File NUM_REQUESTS requests.
3284 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3285 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3286 // and NUM_REQUESTS onAvailable callbacks to fire.
3287 // See how long it took.
3288 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003289 final int REGISTER_TIME_LIMIT_MS = 200;
3290 final int CONNECT_TIME_LIMIT_MS = 60;
3291 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003292 final int UNREGISTER_TIME_LIMIT_MS = 20;
3293
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003294 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3295 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3296 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3297 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3298
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003299 for (int i = 0; i < NUM_REQUESTS; i++) {
3300 callbacks[i] = new NetworkCallback() {
3301 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3302 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3303 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003304 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003305
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003306 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3307 for (NetworkCallback cb : callbacks) {
3308 mCm.registerNetworkCallback(request, cb);
3309 }
3310 });
3311
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003312 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3313 // Don't request that the network validate, because otherwise connect() will block until
3314 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3315 // and we won't actually measure anything.
3316 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003317
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003318 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003319 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003320 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003321 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3322 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3323 onAvailableDispatchingDuration));
3324 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3325 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3326 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003327
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003328 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003329 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003330 mWiFiNetworkAgent.adjustScore(40);
3331 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003332
3333 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003334 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003335 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003336 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3337 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3338 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3339 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3340 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003341
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003342 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3343 for (NetworkCallback cb : callbacks) {
3344 mCm.unregisterNetworkCallback(cb);
3345 }
3346 });
3347 }
3348
3349 private long durationOf(Runnable fn) {
3350 long startTime = SystemClock.elapsedRealtime();
3351 fn.run();
3352 return SystemClock.elapsedRealtime() - startTime;
3353 }
3354
3355 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3356 long timeTaken = durationOf(fn);
3357 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003358 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003359 assertTrue(msg, timeTaken <= timeLimit);
3360 }
3361
3362 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3363 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09003364 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003365 } catch (InterruptedException e) {}
3366 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003367 }
3368
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003369 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003370 public void testMobileDataAlwaysOn() throws Exception {
3371 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3372 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3373 .addTransportType(TRANSPORT_CELLULAR).build();
3374 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3375
3376 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3377 handlerThread.start();
3378 NetworkCapabilities filter = new NetworkCapabilities()
3379 .addTransportType(TRANSPORT_CELLULAR)
3380 .addCapability(NET_CAPABILITY_INTERNET);
3381 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3382 mServiceContext, "testFactory", filter);
3383 testFactory.setScoreFilter(40);
3384
3385 // Register the factory and expect it to start looking for a network.
Chalard Jean08577fc2018-05-02 21:14:54 +09003386 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003387 testFactory.register();
3388 testFactory.waitForNetworkRequests(1);
3389 assertTrue(testFactory.getMyStartRequested());
3390
3391 // Bring up wifi. The factory stops looking for a network.
3392 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Chalard Jean08577fc2018-05-02 21:14:54 +09003393 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3394 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003395 mWiFiNetworkAgent.connect(true);
Chalard Jean08577fc2018-05-02 21:14:54 +09003396 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003397 assertFalse(testFactory.getMyStartRequested());
3398
3399 ContentResolver cr = mServiceContext.getContentResolver();
3400
3401 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean08577fc2018-05-02 21:14:54 +09003402 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003403 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003404 testFactory.waitForNetworkRequests(2);
3405 assertTrue(testFactory.getMyStartRequested());
3406
3407 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003408 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003409 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Chalard Jean08577fc2018-05-02 21:14:54 +09003410 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003411 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003412 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003413 testFactory.waitForNetworkRequests(2);
3414 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3415
3416 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003417 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003418 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003419 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003420
3421 // Turn off mobile data always on and expect the request to disappear...
3422 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003423 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003424 testFactory.waitForNetworkRequests(1);
3425
3426 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003427 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003428 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003429
3430 testFactory.unregister();
3431 mCm.unregisterNetworkCallback(cellNetworkCallback);
3432 handlerThread.quit();
3433 }
3434
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003435 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003436 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003437 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003438 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003439 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3440
Erik Kline065ab6e2016-10-02 18:02:14 +09003441 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003442 String[] values = new String[] {null, "0", "1"};
3443 for (int i = 0; i < values.length; i++) {
3444 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003445 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003446 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003447 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003448 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003449 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003450 }
3451
Erik Kline065ab6e2016-10-02 18:02:14 +09003452 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003453
3454 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003455 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003456 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003457 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003458 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003459
3460 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003461 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003462 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003463 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003464 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003465
3466 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003467 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003468 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003469 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003470 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003471 }
3472
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003473 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003474 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003475 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003476 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003477
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003478 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003479 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003480
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003481 // File a request for cell to ensure it doesn't go down.
3482 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3483 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3484 .addTransportType(TRANSPORT_CELLULAR).build();
3485 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3486
3487 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3488 mCm.registerDefaultNetworkCallback(defaultCallback);
3489
3490 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3491 .addTransportType(TRANSPORT_WIFI)
3492 .addCapability(NET_CAPABILITY_VALIDATED)
3493 .build();
3494 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3495 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3496
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003497 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003498 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003499
3500 // Bring up validated cell.
3501 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3502 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003503 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3504 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003505 Network cellNetwork = mCellNetworkAgent.getNetwork();
3506
3507 // Bring up validated wifi.
3508 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3509 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003510 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3511 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003512 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3513
3514 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003515 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003516 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003517 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003518 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3519
3520 // Because avoid bad wifi is off, we don't switch to cellular.
3521 defaultCallback.assertNoCallback();
3522 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3523 NET_CAPABILITY_VALIDATED));
3524 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3525 NET_CAPABILITY_VALIDATED));
3526 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3527
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003528 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3529 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003530 tracker.configRestrictsAvoidBadWifi = false;
3531 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003532 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003533 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3534
3535 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003536 tracker.configRestrictsAvoidBadWifi = true;
3537 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003538 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003539 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3540
3541 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3542 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003543 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003544 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3545 NET_CAPABILITY_VALIDATED));
3546 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3547 NET_CAPABILITY_VALIDATED));
3548 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3549
3550 // Disconnect and reconnect wifi to clear the one-time switch above.
3551 mWiFiNetworkAgent.disconnect();
3552 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3553 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003554 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3555 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003556 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3557
3558 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003559 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003560 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003561 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003562 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3563
3564 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003565 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003566 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003567
3568 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003569 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003570 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3571 NET_CAPABILITY_VALIDATED));
3572 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3573 NET_CAPABILITY_VALIDATED));
3574 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3575
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003576 // Simulate the user turning the cellular fallback setting off and then on.
3577 // We switch to wifi and then to cell.
3578 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003579 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003580 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003581 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3582 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003583 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003584 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003585 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3586
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003587 // If cell goes down, we switch to wifi.
3588 mCellNetworkAgent.disconnect();
3589 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003590 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003591 validatedWifiCallback.assertNoCallback();
3592
3593 mCm.unregisterNetworkCallback(cellNetworkCallback);
3594 mCm.unregisterNetworkCallback(validatedWifiCallback);
3595 mCm.unregisterNetworkCallback(defaultCallback);
3596 }
3597
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003598 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003599 public void testMeteredMultipathPreferenceSetting() throws Exception {
3600 final ContentResolver cr = mServiceContext.getContentResolver();
3601 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3602 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3603
3604 for (int config : Arrays.asList(0, 3, 2)) {
3605 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3606 tracker.configMeteredMultipathPreference = config;
3607 Settings.Global.putString(cr, settingName, setting);
3608 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003609 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003610
3611 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3612 String msg = String.format("config=%d, setting=%s", config, setting);
3613 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3614 }
3615 }
3616 }
3617
Erik Kline3841a482015-11-25 12:49:38 +09003618 /**
3619 * Validate that a satisfied network request does not trigger onUnavailable() once the
3620 * time-out period expires.
3621 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003622 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003623 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3624 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3625 NetworkCapabilities.TRANSPORT_WIFI).build();
3626 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003627 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003628
3629 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3630 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003631 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003632 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003633
3634 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003635 networkCallback.assertNoCallback();
3636 }
3637
3638 /**
3639 * Validate that a satisfied network request followed by a disconnected (lost) network does
3640 * not trigger onUnavailable() once the time-out period expires.
3641 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003642 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003643 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3644 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3645 NetworkCapabilities.TRANSPORT_WIFI).build();
3646 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003647 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003648
3649 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3650 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003651 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003652 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003653 mWiFiNetworkAgent.disconnect();
3654 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3655
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003656 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003657 networkCallback.assertNoCallback();
3658 }
3659
3660 /**
3661 * Validate that when a time-out is specified for a network request the onUnavailable()
3662 * callback is called when time-out expires. Then validate that if network request is
3663 * (somehow) satisfied - the callback isn't called later.
3664 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003665 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003666 public void testTimedoutNetworkRequest() {
3667 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3668 NetworkCapabilities.TRANSPORT_WIFI).build();
3669 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003670 final int timeoutMs = 10;
3671 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003672
3673 // pass timeout and validate that UNAVAILABLE is called
3674 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3675
3676 // create a network satisfying request - validate that request not triggered
3677 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3678 mWiFiNetworkAgent.connect(false);
3679 networkCallback.assertNoCallback();
3680 }
3681
3682 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003683 * Validate that when a network request is unregistered (cancelled), no posterior event can
3684 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003685 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003686 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003687 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003688 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3689 NetworkCapabilities.TRANSPORT_WIFI).build();
3690 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003691 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003692
Hugo Benichidfb559a2016-12-20 14:57:49 +09003693 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003694 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003695 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3696 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003697 networkCallback.assertNoCallback();
3698
3699 // create a network satisfying request - validate that request not triggered
3700 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3701 mWiFiNetworkAgent.connect(false);
3702 networkCallback.assertNoCallback();
3703 }
3704
Etan Cohenae574a82019-01-08 12:09:18 -08003705 /**
3706 * Validate the callback flow for a factory releasing a request as unfulfillable.
3707 */
3708 @Test
3709 public void testUnfulfillableNetworkRequest() throws Exception {
3710 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3711 NetworkCapabilities.TRANSPORT_WIFI).build();
3712 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3713
3714 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3715 handlerThread.start();
3716 NetworkCapabilities filter = new NetworkCapabilities()
3717 .addTransportType(TRANSPORT_WIFI)
3718 .addCapability(NET_CAPABILITY_INTERNET);
3719 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3720 mServiceContext, "testFactory", filter);
3721 testFactory.setScoreFilter(40);
3722
3723 // Register the factory and expect it to receive the default request.
3724 testFactory.expectAddRequestsWithScores(0);
3725 testFactory.register();
3726 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3727
3728 assertEquals(1, requests.size()); // have 1 request at this point
3729 int origRequestId = requests.valueAt(0).requestId;
3730
3731 // Now file the test request and expect it.
3732 testFactory.expectAddRequestsWithScores(0);
3733 mCm.requestNetwork(nr, networkCallback);
3734 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3735
3736 int newRequestId = 0;
3737 for (int i = 0; i < requests.size(); ++i) {
3738 if (requests.valueAt(i).requestId != origRequestId) {
3739 newRequestId = requests.valueAt(i).requestId;
3740 break;
3741 }
3742 }
3743
3744 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
3745 testFactory.expectRemoveRequests(1);
3746 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3747 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3748 testFactory.waitForRequests();
3749
3750 testFactory.unregister();
3751 handlerThread.quit();
3752 }
3753
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003754 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3755
3756 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3757
3758 private class CallbackValue {
3759 public CallbackType callbackType;
3760 public int error;
3761
3762 public CallbackValue(CallbackType type) {
3763 this.callbackType = type;
3764 this.error = PacketKeepalive.SUCCESS;
3765 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3766 }
3767
3768 public CallbackValue(CallbackType type, int error) {
3769 this.callbackType = type;
3770 this.error = error;
3771 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3772 }
3773
3774 @Override
3775 public boolean equals(Object o) {
3776 return o instanceof CallbackValue &&
3777 this.callbackType == ((CallbackValue) o).callbackType &&
3778 this.error == ((CallbackValue) o).error;
3779 }
3780
3781 @Override
3782 public String toString() {
3783 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3784 }
3785 }
3786
junyulai7c469172019-01-16 20:23:34 +08003787 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003788
3789 @Override
3790 public void onStarted() {
3791 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3792 }
3793
3794 @Override
3795 public void onStopped() {
3796 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3797 }
3798
3799 @Override
3800 public void onError(int error) {
3801 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3802 }
3803
3804 private void expectCallback(CallbackValue callbackValue) {
3805 try {
3806 assertEquals(
3807 callbackValue,
3808 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3809 } catch (InterruptedException e) {
3810 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3811 }
3812 }
3813
3814 public void expectStarted() {
3815 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3816 }
3817
3818 public void expectStopped() {
3819 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3820 }
3821
3822 public void expectError(int error) {
3823 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3824 }
3825 }
3826
junyulai48eac1d42018-12-27 17:25:29 +08003827 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3828
3829 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3830
3831 private class CallbackValue {
3832 public CallbackType callbackType;
3833 public int error;
3834
3835 CallbackValue(CallbackType type) {
3836 this.callbackType = type;
3837 this.error = SocketKeepalive.SUCCESS;
3838 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3839 }
3840
3841 CallbackValue(CallbackType type, int error) {
3842 this.callbackType = type;
3843 this.error = error;
3844 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3845 }
3846
3847 @Override
3848 public boolean equals(Object o) {
3849 return o instanceof CallbackValue
3850 && this.callbackType == ((CallbackValue) o).callbackType
3851 && this.error == ((CallbackValue) o).error;
3852 }
3853
3854 @Override
3855 public String toString() {
3856 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3857 error);
3858 }
3859 }
3860
3861 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003862 private final Executor mExecutor;
3863
3864 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3865 mExecutor = executor;
3866 }
junyulai48eac1d42018-12-27 17:25:29 +08003867
3868 @Override
3869 public void onStarted() {
3870 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3871 }
3872
3873 @Override
3874 public void onStopped() {
3875 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3876 }
3877
3878 @Override
3879 public void onError(int error) {
3880 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3881 }
3882
3883 private void expectCallback(CallbackValue callbackValue) {
3884 try {
3885 assertEquals(
3886 callbackValue,
3887 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3888 } catch (InterruptedException e) {
3889 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3890 }
3891 }
3892
3893 public void expectStarted() {
3894 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3895 }
3896
3897 public void expectStopped() {
3898 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3899 }
3900
3901 public void expectError(int error) {
3902 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3903 }
junyulai7c469172019-01-16 20:23:34 +08003904
3905 public void assertNoCallback() {
3906 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
3907 CallbackValue cv = mCallbacks.peek();
3908 assertNull("Unexpected callback: " + cv, cv);
3909 }
junyulai48eac1d42018-12-27 17:25:29 +08003910 }
3911
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003912 private Network connectKeepaliveNetwork(LinkProperties lp) {
3913 // Ensure the network is disconnected before we do anything.
3914 if (mWiFiNetworkAgent != null) {
3915 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3916 }
3917
3918 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3919 ConditionVariable cv = waitForConnectivityBroadcasts(1);
3920 mWiFiNetworkAgent.connect(true);
3921 waitFor(cv);
3922 verifyActiveNetwork(TRANSPORT_WIFI);
3923 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003924 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003925 return mWiFiNetworkAgent.getNetwork();
3926 }
3927
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003928 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003929 public void testPacketKeepalives() throws Exception {
3930 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3931 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3932 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3933 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3934 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3935
Nathan Harold63dd8132018-02-14 13:09:45 -08003936 final int validKaInterval = 15;
3937 final int invalidKaInterval = 9;
3938
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003939 LinkProperties lp = new LinkProperties();
3940 lp.setInterfaceName("wlan12");
3941 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3942 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3943 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3944 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3945
3946 Network notMyNet = new Network(61234);
3947 Network myNet = connectKeepaliveNetwork(lp);
3948
3949 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3950 PacketKeepalive ka;
3951
3952 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003953 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003954 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3955
Nathan Harold63dd8132018-02-14 13:09:45 -08003956 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003957 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3958
Nathan Harold63dd8132018-02-14 13:09:45 -08003959 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003960 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3961
Nathan Harold63dd8132018-02-14 13:09:45 -08003962 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003963 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3964
Nathan Harold63dd8132018-02-14 13:09:45 -08003965 // NAT-T is only supported for IPv4.
3966 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3967 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003968
Nathan Harold63dd8132018-02-14 13:09:45 -08003969 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003970 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3971
Nathan Harold63dd8132018-02-14 13:09:45 -08003972 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003973 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3974
Nathan Harold63dd8132018-02-14 13:09:45 -08003975 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003976 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3977
Nathan Harold63dd8132018-02-14 13:09:45 -08003978 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003979 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3980
3981 // Check that a started keepalive can be stopped.
3982 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003983 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003984 callback.expectStarted();
3985 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
3986 ka.stop();
3987 callback.expectStopped();
3988
3989 // Check that deleting the IP address stops the keepalive.
3990 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003991 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003992 callback.expectStarted();
3993 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3994 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3995 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3996 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3997 mWiFiNetworkAgent.sendLinkProperties(lp);
3998
3999 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004000 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004001 callback.expectStarted();
4002 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004003 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004004 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4005
4006 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004007 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004008 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004009 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004010 ka.stop();
4011
4012 // Reconnect.
4013 myNet = connectKeepaliveNetwork(lp);
4014 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
4015
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004016 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4017 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004018 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004019 callback.expectStarted();
4020
4021 // The second one gets slot 2.
4022 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4023 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004024 PacketKeepalive ka2 = mCm.startNattKeepalive(
4025 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004026 callback2.expectStarted();
4027
4028 // Now stop the first one and create a third. This also gets slot 1.
4029 ka.stop();
4030 callback.expectStopped();
4031
4032 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4033 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004034 PacketKeepalive ka3 = mCm.startNattKeepalive(
4035 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004036 callback3.expectStarted();
4037
4038 ka2.stop();
4039 callback2.expectStopped();
4040
4041 ka3.stop();
4042 callback3.expectStopped();
4043 }
Udam Sainib7c24872016-01-04 12:16:14 -08004044
junyulaiafe9b492019-03-19 18:50:23 +08004045 @FunctionalInterface
4046 private interface ThrowingConsumer<T> {
4047 void accept(T t) throws Exception;
4048 }
4049
Xiao Maa4637112019-02-07 15:03:57 +09004050 // Helper method to prepare the executor and run test
junyulaiafe9b492019-03-19 18:50:23 +08004051 private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
junyulaie4135282019-01-03 18:50:15 +08004052 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004053 final Executor executorInline = (Runnable r) -> r.run();
4054 functor.accept(executorSingleThread);
junyulaie4135282019-01-03 18:50:15 +08004055 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004056 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004057 }
junyulaie4135282019-01-03 18:50:15 +08004058
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004059 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004060 public void testNattSocketKeepalives() throws Exception {
4061 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4062 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulaie4135282019-01-03 18:50:15 +08004063 }
4064
4065 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004066 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulaie4135282019-01-03 18:50:15 +08004067 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004068 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004069 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4070 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4071 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4072 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4073 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4074
4075 final int validKaInterval = 15;
4076 final int invalidKaInterval = 9;
4077
4078 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004079 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4080 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004081
junyulai48eac1d42018-12-27 17:25:29 +08004082 LinkProperties lp = new LinkProperties();
4083 lp.setInterfaceName("wlan12");
4084 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4085 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4086 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4087 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4088
4089 Network notMyNet = new Network(61234);
4090 Network myNet = connectKeepaliveNetwork(lp);
4091
junyulai7c469172019-01-16 20:23:34 +08004092 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004093
4094 // Attempt to start keepalives with invalid parameters and check for errors.
4095 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004096 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4097 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4098 ka.start(validKaInterval);
4099 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4100 }
junyulai48eac1d42018-12-27 17:25:29 +08004101
4102 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004103 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4104 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4105 ka.start(invalidKaInterval);
4106 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4107 }
junyulai48eac1d42018-12-27 17:25:29 +08004108
4109 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004110 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4111 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4112 ka.start(validKaInterval);
4113 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4114 }
junyulai48eac1d42018-12-27 17:25:29 +08004115
4116 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004117 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4118 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4119 ka.start(validKaInterval);
4120 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4121 }
junyulai48eac1d42018-12-27 17:25:29 +08004122
4123 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004124 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4125 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4126 ka.start(validKaInterval);
4127 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4128 }
junyulai48eac1d42018-12-27 17:25:29 +08004129
4130 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004131 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4132 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4133 ka.start(validKaInterval);
4134 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4135 }
junyulai48eac1d42018-12-27 17:25:29 +08004136
4137 // Check that a started keepalive can be stopped.
4138 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004139 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4140 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4141 ka.start(validKaInterval);
4142 callback.expectStarted();
4143 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4144 ka.stop();
4145 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004146
junyulai0c666972019-03-04 22:45:36 +08004147 // Check that keepalive could be restarted.
4148 ka.start(validKaInterval);
4149 callback.expectStarted();
4150 ka.stop();
4151 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004152
junyulai0c666972019-03-04 22:45:36 +08004153 // Check that keepalive can be restarted without waiting for callback.
4154 ka.start(validKaInterval);
4155 callback.expectStarted();
4156 ka.stop();
4157 ka.start(validKaInterval);
4158 callback.expectStopped();
4159 callback.expectStarted();
4160 ka.stop();
4161 callback.expectStopped();
4162 }
junyulai7c469172019-01-16 20:23:34 +08004163
junyulai48eac1d42018-12-27 17:25:29 +08004164 // Check that deleting the IP address stops the keepalive.
4165 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004166 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4167 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4168 ka.start(validKaInterval);
4169 callback.expectStarted();
4170 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4171 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4172 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4173 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4174 mWiFiNetworkAgent.sendLinkProperties(lp);
4175 }
junyulai48eac1d42018-12-27 17:25:29 +08004176
4177 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004178 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4179 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4180 ka.start(validKaInterval);
4181 callback.expectStarted();
4182 mWiFiNetworkAgent.disconnect();
4183 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4184 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004185
junyulai0c666972019-03-04 22:45:36 +08004186 // ... and that stopping it after that has no adverse effects.
4187 waitForIdle();
4188 final Network myNetAlias = myNet;
4189 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4190 ka.stop();
4191 callback.assertNoCallback();
4192 }
junyulai48eac1d42018-12-27 17:25:29 +08004193
4194 // Reconnect.
4195 myNet = connectKeepaliveNetwork(lp);
4196 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4197
4198 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4199 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004200 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004201 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4202 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4203 ka.start(validKaInterval);
4204 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004205
junyulai0c666972019-03-04 22:45:36 +08004206 // The second one gets slot 2.
4207 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004208 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4209 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004210 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4211 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4212 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4213 ka2.start(validKaInterval);
4214 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004215
junyulai0c666972019-03-04 22:45:36 +08004216 ka.stop();
4217 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004218
junyulai0c666972019-03-04 22:45:36 +08004219 ka2.stop();
4220 callback2.expectStopped();
junyulaie4135282019-01-03 18:50:15 +08004221
junyulai0c666972019-03-04 22:45:36 +08004222 testSocket.close();
4223 testSocket2.close();
4224 }
4225 }
junyulaie4135282019-01-03 18:50:15 +08004226
junyulai15178152019-03-27 11:00:37 +08004227 // Check that there is no port leaked after all keepalives and sockets are closed.
4228 assertFalse(isUdpPortInUse(srcPort));
4229 assertFalse(isUdpPortInUse(srcPort2));
4230
junyulaie4135282019-01-03 18:50:15 +08004231 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004232 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Xiao Maa4637112019-02-07 15:03:57 +09004233 mWiFiNetworkAgent = null;
4234 }
4235
4236 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004237 public void testTcpSocketKeepalives() throws Exception {
4238 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004239 }
4240
4241 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4242 final int srcPortV4 = 12345;
4243 final int srcPortV6 = 23456;
4244 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4245 final InetAddress myIPv6 = InetAddress.getByName("::1");
4246
4247 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004248
4249 final LinkProperties lp = new LinkProperties();
4250 lp.setInterfaceName("wlan12");
4251 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4252 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4253 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4254 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4255
4256 final Network notMyNet = new Network(61234);
4257 final Network myNet = connectKeepaliveNetwork(lp);
4258
4259 final Socket testSocketV4 = new Socket();
4260 final Socket testSocketV6 = new Socket();
4261
junyulai7c469172019-01-16 20:23:34 +08004262 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004263
4264 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4265 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004266 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4267 notMyNet, testSocketV4, executor, callback)) {
4268 ka.start(validKaInterval);
4269 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4270 }
Xiao Maa4637112019-02-07 15:03:57 +09004271
4272 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004273 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4274 myNet, testSocketV4, executor, callback)) {
4275 ka.start(validKaInterval);
4276 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4277 }
Xiao Maa4637112019-02-07 15:03:57 +09004278
4279 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004280 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4281 myNet, testSocketV6, executor, callback)) {
4282 ka.start(validKaInterval);
4283 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4284 }
Xiao Maa4637112019-02-07 15:03:57 +09004285
4286 // Bind the socket address
4287 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4288 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4289
4290 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004291 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4292 myNet, testSocketV4, executor, callback)) {
4293 ka.start(validKaInterval);
4294 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4295 }
Xiao Maa4637112019-02-07 15:03:57 +09004296
4297 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004298 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4299 myNet, testSocketV6, executor, callback)) {
4300 ka.start(validKaInterval);
4301 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4302 }
Xiao Maa4637112019-02-07 15:03:57 +09004303
4304 testSocketV4.close();
4305 testSocketV6.close();
4306
4307 mWiFiNetworkAgent.disconnect();
4308 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4309 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004310 }
4311
junyulai0c666972019-03-04 22:45:36 +08004312 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004313 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4314 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4315 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4316 final int validKaInterval = 15;
4317
4318 // Prepare the target network.
4319 LinkProperties lp = new LinkProperties();
4320 lp.setInterfaceName("wlan12");
4321 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4322 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4323 Network myNet = connectKeepaliveNetwork(lp);
4324 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4325 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4326
4327 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4328
4329 // Prepare the target file descriptor, keep only one instance.
4330 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004331 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4332 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004333 final ParcelFileDescriptor testPfd =
4334 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4335 testSocket.close();
4336 assertTrue(isUdpPortInUse(srcPort));
4337
4338 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4339 // block.
4340 try (SocketKeepalive ka = mCm.createNattKeepalive(
4341 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4342 ka.start(validKaInterval);
4343 callback.expectStarted();
4344 ka.stop();
4345 callback.expectStopped();
4346 }
4347
4348 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4349 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4350 // address.
4351 assertTrue(isUdpPortInUse(srcPort));
4352 final InetSocketAddress sa =
4353 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4354 assertEquals(anyIPv4, sa.getAddress());
4355
4356 testPfd.close();
4357 assertFalse(isUdpPortInUse(srcPort));
4358
4359 mWiFiNetworkAgent.disconnect();
4360 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4361 mWiFiNetworkAgent = null;
4362 }
4363
4364 private static boolean isUdpPortInUse(int port) {
4365 try (DatagramSocket ignored = new DatagramSocket(port)) {
4366 return false;
4367 } catch (IOException ignored) {
4368 return true;
4369 }
4370 }
4371
junyulai48eac1d42018-12-27 17:25:29 +08004372 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004373 public void testGetCaptivePortalServerUrl() throws Exception {
4374 String url = mCm.getCaptivePortalServerUrl();
4375 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4376 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004377
4378 private static class TestNetworkPinner extends NetworkPinner {
4379 public static boolean awaitPin(int timeoutMs) {
4380 synchronized(sLock) {
4381 if (sNetwork == null) {
4382 try {
4383 sLock.wait(timeoutMs);
4384 } catch (InterruptedException e) {}
4385 }
4386 return sNetwork != null;
4387 }
4388 }
4389
4390 public static boolean awaitUnpin(int timeoutMs) {
4391 synchronized(sLock) {
4392 if (sNetwork != null) {
4393 try {
4394 sLock.wait(timeoutMs);
4395 } catch (InterruptedException e) {}
4396 }
4397 return sNetwork == null;
4398 }
4399 }
4400 }
4401
4402 private void assertPinnedToWifiWithCellDefault() {
4403 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4404 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4405 }
4406
4407 private void assertPinnedToWifiWithWifiDefault() {
4408 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4409 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4410 }
4411
4412 private void assertNotPinnedToWifi() {
4413 assertNull(mCm.getBoundNetworkForProcess());
4414 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4415 }
4416
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004417 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004418 public void testNetworkPinner() {
4419 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4420 .addTransportType(TRANSPORT_WIFI)
4421 .build();
4422 assertNull(mCm.getBoundNetworkForProcess());
4423
4424 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4425 assertNull(mCm.getBoundNetworkForProcess());
4426
4427 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4428 mCellNetworkAgent.connect(true);
4429 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4430 mWiFiNetworkAgent.connect(false);
4431
4432 // When wi-fi connects, expect to be pinned.
4433 assertTrue(TestNetworkPinner.awaitPin(100));
4434 assertPinnedToWifiWithCellDefault();
4435
4436 // Disconnect and expect the pin to drop.
4437 mWiFiNetworkAgent.disconnect();
4438 assertTrue(TestNetworkPinner.awaitUnpin(100));
4439 assertNotPinnedToWifi();
4440
4441 // Reconnecting does not cause the pin to come back.
4442 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4443 mWiFiNetworkAgent.connect(false);
4444 assertFalse(TestNetworkPinner.awaitPin(100));
4445 assertNotPinnedToWifi();
4446
4447 // Pinning while connected causes the pin to take effect immediately.
4448 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4449 assertTrue(TestNetworkPinner.awaitPin(100));
4450 assertPinnedToWifiWithCellDefault();
4451
4452 // Explicitly unpin and expect to use the default network again.
4453 TestNetworkPinner.unpin();
4454 assertNotPinnedToWifi();
4455
4456 // Disconnect cell and wifi.
4457 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4458 mCellNetworkAgent.disconnect();
4459 mWiFiNetworkAgent.disconnect();
4460 waitFor(cv);
4461
4462 // Pinning takes effect even if the pinned network is the default when the pin is set...
4463 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4464 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4465 mWiFiNetworkAgent.connect(false);
4466 assertTrue(TestNetworkPinner.awaitPin(100));
4467 assertPinnedToWifiWithWifiDefault();
4468
4469 // ... and is maintained even when that network is no longer the default.
4470 cv = waitForConnectivityBroadcasts(1);
4471 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4472 mCellNetworkAgent.connect(true);
4473 waitFor(cv);
4474 assertPinnedToWifiWithCellDefault();
4475 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004476
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004477 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004478 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004479 // We can only have 99 callbacks, because MultipathPolicyTracker is
4480 // already one of them.
4481 final int MAX_REQUESTS = 99;
4482 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004483 final int INTENTS = 10;
4484 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4485
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004486 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004487 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004488
Hugo Benichi893a7622017-09-29 09:34:08 +09004489 int j = 0;
4490 while (j++ < CALLBACKS / 2) {
4491 NetworkCallback cb = new NetworkCallback();
4492 mCm.requestNetwork(networkRequest, cb);
4493 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004494 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004495 while (j++ < CALLBACKS) {
4496 NetworkCallback cb = new NetworkCallback();
4497 mCm.registerNetworkCallback(networkRequest, cb);
4498 registered.add(cb);
4499 }
4500 j = 0;
4501 while (j++ < INTENTS / 2) {
4502 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4503 mCm.requestNetwork(networkRequest, pi);
4504 registered.add(pi);
4505 }
4506 while (j++ < INTENTS) {
4507 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4508 mCm.registerNetworkCallback(networkRequest, pi);
4509 registered.add(pi);
4510 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004511
Hugo Benichi893a7622017-09-29 09:34:08 +09004512 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004513 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09004514 mCm.requestNetwork(networkRequest, new NetworkCallback());
4515 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09004516 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09004517 try {
4518 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4519 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4520 } catch (TooManyRequestsException expected) {}
4521 try {
4522 mCm.requestNetwork(networkRequest,
4523 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4524 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4525 } catch (TooManyRequestsException expected) {}
4526 try {
4527 mCm.registerNetworkCallback(networkRequest,
4528 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4529 fail("Registering " + MAX_REQUESTS
4530 + " PendingIntent callbacks did not throw exception");
4531 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004532
Hugo Benichi893a7622017-09-29 09:34:08 +09004533 for (Object o : registered) {
4534 if (o instanceof NetworkCallback) {
4535 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004536 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004537 if (o instanceof PendingIntent) {
4538 mCm.unregisterNetworkCallback((PendingIntent)o);
4539 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004540 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004541 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004542
4543 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4544 for (int i = 0; i < MAX_REQUESTS; i++) {
4545 NetworkCallback networkCallback = new NetworkCallback();
4546 mCm.requestNetwork(networkRequest, networkCallback);
4547 mCm.unregisterNetworkCallback(networkCallback);
4548 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004549 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004550
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004551 for (int i = 0; i < MAX_REQUESTS; i++) {
4552 NetworkCallback networkCallback = new NetworkCallback();
4553 mCm.registerNetworkCallback(networkRequest, networkCallback);
4554 mCm.unregisterNetworkCallback(networkCallback);
4555 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004556 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004557
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004558 for (int i = 0; i < MAX_REQUESTS; i++) {
4559 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004560 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004561 mCm.requestNetwork(networkRequest, pendingIntent);
4562 mCm.unregisterNetworkCallback(pendingIntent);
4563 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004564 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004565
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004566 for (int i = 0; i < MAX_REQUESTS; i++) {
4567 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004568 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004569 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4570 mCm.unregisterNetworkCallback(pendingIntent);
4571 }
4572 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004573
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004574 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004575 public void testNetworkInfoOfTypeNone() {
4576 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4577
4578 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09004579 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004580 assertNull(mCm.getActiveNetworkInfo());
4581
4582 Network[] allNetworks = mCm.getAllNetworks();
4583 assertLength(1, allNetworks);
4584 Network network = allNetworks[0];
4585 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4586 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4587
4588 final NetworkRequest request =
4589 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4590 final TestNetworkCallback callback = new TestNetworkCallback();
4591 mCm.registerNetworkCallback(request, callback);
4592
Hugo Benichic1014502017-07-19 10:10:52 +09004593 // Bring up wifi aware network.
4594 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004595 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004596
4597 assertNull(mCm.getActiveNetworkInfo());
4598 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004599 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004600 // of this test. Fix it and uncomment the assert below.
4601 //assertEmpty(mCm.getAllNetworkInfo());
4602
Hugo Benichic1014502017-07-19 10:10:52 +09004603 // Disconnect wifi aware network.
4604 wifiAware.disconnect();
4605 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004606 mCm.unregisterNetworkCallback(callback);
4607
4608 verifyNoNetwork();
4609 if (broadcastCV.block(10)) {
4610 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4611 }
4612 }
4613
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004614 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004615 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4616 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4617 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4618 assertNull(mCm.getNetworkForType(TYPE_NONE));
4619 assertNull(mCm.getLinkProperties(TYPE_NONE));
4620 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4621
4622 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4623 IllegalArgumentException.class);
4624
4625 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4626 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4627 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4628 // TODO: let test context have configuration application target sdk version
4629 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4630 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4631 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4632 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4633 }
4634
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004635 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01004636 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4637 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4638 .addTransportType(TRANSPORT_WIFI).build();
4639 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4640 mCm.registerNetworkCallback(networkRequest, networkCallback);
4641
4642 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004643 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004644 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4645 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4646 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4647 lp.addLinkAddress(myIpv4Address);
4648 lp.addRoute(myIpv4DefaultRoute);
4649
4650 // Verify direct routes are added when network agent is first registered in
4651 // ConnectivityService.
4652 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4653 networkAgent.connect(true);
4654 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4655 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4656 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4657 networkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004658 networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004659 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4660 networkCallback.assertNoCallback();
4661 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4662 Arrays.asList(myIpv4DefaultRoute));
4663 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4664 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4665
4666 // Verify direct routes are added during subsequent link properties updates.
4667 LinkProperties newLp = new LinkProperties(lp);
4668 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4669 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4670 newLp.addLinkAddress(myIpv6Address1);
4671 newLp.addLinkAddress(myIpv6Address2);
4672 networkAgent.sendLinkProperties(newLp);
4673 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4674 networkCallback.assertNoCallback();
4675 checkDirectlyConnectedRoutes(cbi.arg,
4676 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4677 Arrays.asList(myIpv4DefaultRoute));
4678 mCm.unregisterNetworkCallback(networkCallback);
4679 }
4680
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004681 @Test
4682 public void testStatsIfacesChanged() throws Exception {
4683 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004684 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4685
Varun Anand02c50ef2019-02-07 14:13:13 -08004686 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4687 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4688
4689 LinkProperties cellLp = new LinkProperties();
4690 cellLp.setInterfaceName(MOBILE_IFNAME);
4691 LinkProperties wifiLp = new LinkProperties();
4692 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004693
4694 // Simple connection should have updated ifaces
4695 mCellNetworkAgent.connect(false);
Varun Anand02c50ef2019-02-07 14:13:13 -08004696 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004697 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004698 verify(mStatsService, atLeastOnce())
4699 .forceUpdateIfaces(
4700 eq(onlyCell),
4701 eq(new VpnInfo[0]),
4702 any(NetworkState[].class),
4703 eq(MOBILE_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004704 reset(mStatsService);
4705
4706 // Default network switch should update ifaces.
4707 mWiFiNetworkAgent.connect(false);
Varun Anand02c50ef2019-02-07 14:13:13 -08004708 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004709 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004710 assertEquals(wifiLp, mService.getActiveLinkProperties());
4711 verify(mStatsService, atLeastOnce())
4712 .forceUpdateIfaces(
4713 eq(onlyWifi),
4714 eq(new VpnInfo[0]),
4715 any(NetworkState[].class),
4716 eq(WIFI_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004717 reset(mStatsService);
4718
4719 // Disconnect should update ifaces.
4720 mWiFiNetworkAgent.disconnect();
4721 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004722 verify(mStatsService, atLeastOnce())
4723 .forceUpdateIfaces(
4724 eq(onlyCell),
4725 eq(new VpnInfo[0]),
4726 any(NetworkState[].class),
4727 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004728 reset(mStatsService);
4729
4730 // Metered change should update ifaces
4731 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4732 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004733 verify(mStatsService, atLeastOnce())
4734 .forceUpdateIfaces(
4735 eq(onlyCell),
4736 eq(new VpnInfo[0]),
4737 any(NetworkState[].class),
4738 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004739 reset(mStatsService);
4740
4741 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4742 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004743 verify(mStatsService, atLeastOnce())
4744 .forceUpdateIfaces(
4745 eq(onlyCell),
4746 eq(new VpnInfo[0]),
4747 any(NetworkState[].class),
4748 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004749 reset(mStatsService);
4750
4751 // Captive portal change shouldn't update ifaces
4752 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4753 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004754 verify(mStatsService, never())
4755 .forceUpdateIfaces(
4756 eq(onlyCell),
4757 eq(new VpnInfo[0]),
4758 any(NetworkState[].class),
4759 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004760 reset(mStatsService);
4761
4762 // Roaming change should update ifaces
4763 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4764 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004765 verify(mStatsService, atLeastOnce())
4766 .forceUpdateIfaces(
4767 eq(onlyCell),
4768 eq(new VpnInfo[0]),
4769 any(NetworkState[].class),
4770 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004771 reset(mStatsService);
4772 }
4773
Erik Klinee89953b2018-01-11 16:11:10 +09004774 @Test
4775 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004776 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4777 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
4778
4779 // Clear any interactions that occur as a result of CS starting up.
4780 reset(mNetworkManagementService);
4781
4782 final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Klinee89953b2018-01-11 16:11:10 +09004783 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4784 waitForIdle();
4785 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
Erik Kline79c6d052018-03-21 07:18:33 -07004786 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
4787 verifyNoMoreInteractions(mNetworkManagementService);
Erik Klinee89953b2018-01-11 16:11:10 +09004788
4789 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004790 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004791 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4792 // "is-reachable" testing in order to not program netd with unreachable
4793 // nameservers that it might try repeated to validate.
4794 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004795 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4796 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004797 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004798 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4799 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004800 mCellNetworkAgent.sendLinkProperties(cellLp);
4801 mCellNetworkAgent.connect(false);
4802 waitForIdle();
Erik Klinee89953b2018-01-11 16:11:10 +09004803 // CS tells netd about the empty DNS config for this network.
Erik Kline79c6d052018-03-21 07:18:33 -07004804 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4805 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
Erik Klinee89953b2018-01-11 16:11:10 +09004806 reset(mNetworkManagementService);
4807
4808 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4809 mCellNetworkAgent.sendLinkProperties(cellLp);
4810 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004811 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004812 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07004813 eq(""), tlsServers.capture());
Erik Klinee89953b2018-01-11 16:11:10 +09004814 assertEquals(1, mStringArrayCaptor.getValue().length);
4815 assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004816 // Opportunistic mode.
4817 assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
Erik Klinee89953b2018-01-11 16:11:10 +09004818 reset(mNetworkManagementService);
4819
4820 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4821 mCellNetworkAgent.sendLinkProperties(cellLp);
4822 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004823 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004824 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07004825 eq(""), tlsServers.capture());
Erik Kline117e7f32018-03-04 21:01:01 +09004826 assertEquals(2, mStringArrayCaptor.getValue().length);
4827 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4828 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004829 // Opportunistic mode.
4830 assertEquals(2, tlsServers.getValue().length);
4831 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4832 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline117e7f32018-03-04 21:01:01 +09004833 reset(mNetworkManagementService);
4834
4835 final String TLS_SPECIFIER = "tls.example.com";
4836 final String TLS_SERVER6 = "2001:db8:53::53";
4837 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4838 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004839 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4840 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4841
Erik Kline117e7f32018-03-04 21:01:01 +09004842 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004843 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004844 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4845 eq(TLS_SPECIFIER), eq(TLS_SERVERS));
Erik Klinee89953b2018-01-11 16:11:10 +09004846 assertEquals(2, mStringArrayCaptor.getValue().length);
4847 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4848 new String[]{"2001:db8::1", "192.0.2.1"}));
4849 reset(mNetworkManagementService);
4850 }
4851
Erik Kline79c6d052018-03-21 07:18:33 -07004852 @Test
4853 public void testPrivateDnsSettingsChange() throws Exception {
4854 final String[] EMPTY_STRING_ARRAY = new String[0];
4855 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
4856
4857 // Clear any interactions that occur as a result of CS starting up.
4858 reset(mNetworkManagementService);
4859
4860 // The default on Android is opportunistic mode ("Automatic").
4861 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4862
dalyk1fcb7392018-03-05 12:42:22 -05004863 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4864 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4865 .addTransportType(TRANSPORT_CELLULAR).build();
4866 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4867
Erik Kline79c6d052018-03-21 07:18:33 -07004868 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4869 waitForIdle();
4870 // CS tells netd about the empty DNS config for this network.
4871 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
4872 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
4873 verifyNoMoreInteractions(mNetworkManagementService);
4874
4875 final LinkProperties cellLp = new LinkProperties();
4876 cellLp.setInterfaceName(MOBILE_IFNAME);
4877 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4878 // "is-reachable" testing in order to not program netd with unreachable
4879 // nameservers that it might try repeated to validate.
4880 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4881 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4882 MOBILE_IFNAME));
4883 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4884 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4885 MOBILE_IFNAME));
4886 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4887 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4888
4889 mCellNetworkAgent.sendLinkProperties(cellLp);
4890 mCellNetworkAgent.connect(false);
4891 waitForIdle();
4892 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4893 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4894 eq(""), tlsServers.capture());
4895 assertEquals(2, mStringArrayCaptor.getValue().length);
4896 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4897 new String[]{"2001:db8::1", "192.0.2.1"}));
4898 // Opportunistic mode.
4899 assertEquals(2, tlsServers.getValue().length);
4900 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4901 new String[]{"2001:db8::1", "192.0.2.1"}));
4902 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004903 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4904 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4905 mCellNetworkAgent);
4906 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4907 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004908 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004909 cellNetworkCallback.assertNoCallback();
4910 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4911 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004912
4913 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
4914 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
4915 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4916 eq(""), eq(EMPTY_STRING_ARRAY));
4917 assertEquals(2, mStringArrayCaptor.getValue().length);
4918 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4919 new String[]{"2001:db8::1", "192.0.2.1"}));
4920 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004921 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004922
4923 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4924 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4925 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4926 eq(""), tlsServers.capture());
4927 assertEquals(2, mStringArrayCaptor.getValue().length);
4928 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4929 new String[]{"2001:db8::1", "192.0.2.1"}));
4930 assertEquals(2, tlsServers.getValue().length);
4931 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4932 new String[]{"2001:db8::1", "192.0.2.1"}));
4933 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004934 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004935
dalyk1fcb7392018-03-05 12:42:22 -05004936 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4937 // Can't test dns configuration for strict mode without properly mocking
4938 // out the DNS lookups, but can test that LinkProperties is updated.
4939 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4940 mCellNetworkAgent);
4941 cellNetworkCallback.assertNoCallback();
4942 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4943 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
4944 }
4945
4946 @Test
4947 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4948 // The default on Android is opportunistic mode ("Automatic").
4949 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4950
4951 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4952 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4953 .addTransportType(TRANSPORT_CELLULAR).build();
4954 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4955
4956 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4957 waitForIdle();
4958 LinkProperties lp = new LinkProperties();
4959 mCellNetworkAgent.sendLinkProperties(lp);
4960 mCellNetworkAgent.connect(false);
4961 waitForIdle();
4962 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4963 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4964 mCellNetworkAgent);
4965 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4966 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004967 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004968 cellNetworkCallback.assertNoCallback();
4969 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4970 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4971 Set<InetAddress> dnsServers = new HashSet<>();
4972 checkDnsServers(cbi.arg, dnsServers);
4973
4974 // Send a validation event for a server that is not part of the current
4975 // resolver config. The validation event should be ignored.
4976 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4977 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4978 cellNetworkCallback.assertNoCallback();
4979
4980 // Add a dns server to the LinkProperties.
4981 LinkProperties lp2 = new LinkProperties(lp);
4982 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4983 mCellNetworkAgent.sendLinkProperties(lp2);
4984 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4985 mCellNetworkAgent);
4986 cellNetworkCallback.assertNoCallback();
4987 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4988 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4989 dnsServers.add(InetAddress.getByName("145.100.185.16"));
4990 checkDnsServers(cbi.arg, dnsServers);
4991
4992 // Send a validation event containing a hostname that is not part of
4993 // the current resolver config. The validation event should be ignored.
4994 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4995 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4996 cellNetworkCallback.assertNoCallback();
4997
4998 // Send a validation event where validation failed.
4999 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5000 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5001 cellNetworkCallback.assertNoCallback();
5002
5003 // Send a validation event where validation succeeded for a server in
5004 // the current resolver config. A LinkProperties callback with updated
5005 // private dns fields should be sent.
5006 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5007 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
5008 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5009 mCellNetworkAgent);
5010 cellNetworkCallback.assertNoCallback();
5011 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5012 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5013 checkDnsServers(cbi.arg, dnsServers);
5014
5015 // The private dns fields in LinkProperties should be preserved when
5016 // the network agent sends unrelated changes.
5017 LinkProperties lp3 = new LinkProperties(lp2);
5018 lp3.setMtu(1300);
5019 mCellNetworkAgent.sendLinkProperties(lp3);
5020 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5021 mCellNetworkAgent);
5022 cellNetworkCallback.assertNoCallback();
5023 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5024 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5025 checkDnsServers(cbi.arg, dnsServers);
5026 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
5027
5028 // Removing the only validated server should affect the private dns
5029 // fields in LinkProperties.
5030 LinkProperties lp4 = new LinkProperties(lp3);
5031 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5032 mCellNetworkAgent.sendLinkProperties(lp4);
5033 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5034 mCellNetworkAgent);
5035 cellNetworkCallback.assertNoCallback();
5036 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5037 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5038 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
5039 checkDnsServers(cbi.arg, dnsServers);
5040 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005041 }
5042
Rubin Xu1bb5c082017-09-05 18:40:49 +01005043 private void checkDirectlyConnectedRoutes(Object callbackObj,
5044 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5045 assertTrue(callbackObj instanceof LinkProperties);
5046 LinkProperties lp = (LinkProperties) callbackObj;
5047
5048 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5049 expectedRoutes.addAll(otherRoutes);
5050 for (LinkAddress address : linkAddresses) {
5051 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5052 // Duplicates in linkAddresses are considered failures
5053 assertTrue(expectedRoutes.add(localRoute));
5054 }
5055 List<RouteInfo> observedRoutes = lp.getRoutes();
5056 assertEquals(expectedRoutes.size(), observedRoutes.size());
5057 assertTrue(observedRoutes.containsAll(expectedRoutes));
5058 }
5059
dalyk1fcb7392018-03-05 12:42:22 -05005060 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5061 assertTrue(callbackObj instanceof LinkProperties);
5062 LinkProperties lp = (LinkProperties) callbackObj;
5063 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5064 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5065 }
5066
Hugo Benichifed512a2017-06-26 10:06:49 +09005067 private static <T> void assertEmpty(T[] ts) {
5068 int length = ts.length;
5069 assertEquals("expected empty array, but length was " + length, 0, length);
5070 }
5071
5072 private static <T> void assertLength(int expected, T[] got) {
5073 int length = got.length;
5074 assertEquals(String.format("expected array of length %s, but length was %s for %s",
5075 expected, length, Arrays.toString(got)), expected, length);
5076 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09005077
5078 private static <T> void assertException(Runnable block, Class<T> expected) {
5079 try {
5080 block.run();
5081 fail("Expected exception of type " + expected);
5082 } catch (Exception got) {
5083 if (!got.getClass().equals(expected)) {
5084 fail("Expected exception of type " + expected + " but got " + got);
5085 }
5086 return;
5087 }
5088 }
Chalard Jean0b214af2018-01-12 17:22:49 +09005089
5090 @Test
5091 public void testVpnNetworkActive() {
5092 final int uid = Process.myUid();
5093
5094 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005095 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005096 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5097 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005098 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005099 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5100 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5101 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005102 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5103 .addTransportType(TRANSPORT_WIFI).build();
5104 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005105 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005106 .addTransportType(TRANSPORT_VPN).build();
5107 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005108 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005109 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5110 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005111 mCm.registerDefaultNetworkCallback(defaultCallback);
5112 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005113
5114 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5115 mWiFiNetworkAgent.connect(false);
5116
5117 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005118 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005119 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005120 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005121 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005122 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005123
5124 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5125 final ArraySet<UidRange> ranges = new ArraySet<>();
5126 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005127 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5128 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005129 // VPN networks do not satisfy the default request and are automatically validated
5130 // by NetworkMonitor
Lorenzo Colittied3168e2019-01-23 17:54:08 +09005131 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005132 vpnNetworkAgent.setNetworkValid();
5133
Chalard Jean0b214af2018-01-12 17:22:49 +09005134 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005135 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005136 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005137
5138 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005139 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005140 wifiNetworkCallback.assertNoCallback();
5141 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005142 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5143 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005144
5145 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005146 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09005147 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005148 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5149 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005150
5151 ranges.clear();
5152 vpnNetworkAgent.setUids(ranges);
5153
5154 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005155 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005156 wifiNetworkCallback.assertNoCallback();
5157 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5158
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005159 // TODO : The default network callback should actually get a LOST call here (also see the
5160 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5161 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5162 // can't currently update their UIDs without disconnecting, so this does not matter too
5163 // much, but that is the reason the test here has to check for an update to the
5164 // capabilities instead of the expected LOST then AVAILABLE.
5165 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5166
Chalard Jean0b214af2018-01-12 17:22:49 +09005167 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005168 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005169 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005170
5171 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005172 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005173 wifiNetworkCallback.assertNoCallback();
5174 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005175 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5176 // happen outside of the test, ConnectivityService does not rematch callbacks.
5177 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005178
5179 mWiFiNetworkAgent.disconnect();
5180
5181 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005182 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005183 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5184 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005185 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005186
5187 vpnNetworkAgent.disconnect();
5188
5189 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005190 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005191 wifiNetworkCallback.assertNoCallback();
5192 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005193 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5194 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005195
5196 mCm.unregisterNetworkCallback(genericNetworkCallback);
5197 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5198 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005199 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005200 }
Chalard Jean26400492018-04-18 20:18:38 +09005201
5202 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005203 public void testVpnWithoutInternet() {
Chalard Jean26400492018-04-18 20:18:38 +09005204 final int uid = Process.myUid();
5205
5206 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5207 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005208
5209 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5210 mWiFiNetworkAgent.connect(true);
5211
5212 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5213 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5214
5215 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5216 final ArraySet<UidRange> ranges = new ArraySet<>();
5217 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005218 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5219 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005220 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005221 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005222
5223 defaultCallback.assertNoCallback();
5224 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5225
5226 vpnNetworkAgent.disconnect();
5227 defaultCallback.assertNoCallback();
5228
Varun Anand4fa80e82019-02-06 10:13:38 -08005229 mCm.unregisterNetworkCallback(defaultCallback);
5230 }
5231
5232 @Test
5233 public void testVpnWithInternet() {
5234 final int uid = Process.myUid();
5235
5236 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5237 mCm.registerDefaultNetworkCallback(defaultCallback);
5238
5239 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5240 mWiFiNetworkAgent.connect(true);
5241
5242 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5243 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5244
5245 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5246 final ArraySet<UidRange> ranges = new ArraySet<>();
5247 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005248 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5249 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005250 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005251 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005252
Chalard Jean26400492018-04-18 20:18:38 +09005253 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5254 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5255
5256 vpnNetworkAgent.disconnect();
5257 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5258 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5259
Chalard Jean26400492018-04-18 20:18:38 +09005260 mCm.unregisterNetworkCallback(defaultCallback);
5261 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005262
5263 @Test
5264 public void testVpnSetUnderlyingNetworks() {
5265 final int uid = Process.myUid();
5266
5267 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5268 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5269 .removeCapability(NET_CAPABILITY_NOT_VPN)
5270 .addTransportType(TRANSPORT_VPN)
5271 .build();
5272 NetworkCapabilities nc;
5273 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5274 vpnNetworkCallback.assertNoCallback();
5275
5276 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5277 final ArraySet<UidRange> ranges = new ArraySet<>();
5278 ranges.add(new UidRange(uid, uid));
5279 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5280 mMockVpn.connect();
5281 mMockVpn.setUids(ranges);
5282 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5283
5284 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5285 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5286 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5287 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5288 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5289 // For safety reasons a VPN without underlying networks is considered metered.
5290 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5291
5292 // Connect cell and use it as an underlying network.
5293 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5294 mCellNetworkAgent.connect(true);
5295
5296 mService.setUnderlyingNetworksForVpn(
5297 new Network[] { mCellNetworkAgent.getNetwork() });
5298
5299 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5300 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5301 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5302 vpnNetworkAgent);
5303
5304 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5305 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5306 mWiFiNetworkAgent.connect(true);
5307
5308 mService.setUnderlyingNetworksForVpn(
5309 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5310
5311 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5312 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5313 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5314 vpnNetworkAgent);
5315
5316 // Don't disconnect, but note the VPN is not using wifi any more.
5317 mService.setUnderlyingNetworksForVpn(
5318 new Network[] { mCellNetworkAgent.getNetwork() });
5319
5320 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5321 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5322 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5323 vpnNetworkAgent);
5324
5325 // Use Wifi but not cell. Note the VPN is now unmetered.
5326 mService.setUnderlyingNetworksForVpn(
5327 new Network[] { mWiFiNetworkAgent.getNetwork() });
5328
5329 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5330 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5331 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5332 vpnNetworkAgent);
5333
5334 // Use both again.
5335 mService.setUnderlyingNetworksForVpn(
5336 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5337
5338 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5339 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5340 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5341 vpnNetworkAgent);
5342
Chalard Jean6b65ec72018-05-18 22:02:56 +09005343 // Disconnect cell. Receive update without even removing the dead network from the
5344 // underlying networks – it's dead anyway. Not metered any more.
5345 mCellNetworkAgent.disconnect();
5346 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5347 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5348 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5349 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005350
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005351 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005352 mWiFiNetworkAgent.disconnect();
5353 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5354 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005355 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09005356 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005357
5358 mMockVpn.disconnect();
5359 }
junyulai4a192e22018-06-13 15:00:37 +08005360
Mike Yuf9729752018-08-17 15:22:05 +08005361 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005362 public void testNullUnderlyingNetworks() {
5363 final int uid = Process.myUid();
5364
5365 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5366 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5367 .removeCapability(NET_CAPABILITY_NOT_VPN)
5368 .addTransportType(TRANSPORT_VPN)
5369 .build();
5370 NetworkCapabilities nc;
5371 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5372 vpnNetworkCallback.assertNoCallback();
5373
5374 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5375 final ArraySet<UidRange> ranges = new ArraySet<>();
5376 ranges.add(new UidRange(uid, uid));
5377 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5378 mMockVpn.connect();
5379 mMockVpn.setUids(ranges);
5380 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5381
5382 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5383 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5384 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5385 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5386 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5387 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5388 // In case of no default network, VPN is considered metered.
5389 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5390
5391 // Connect to Cell; Cell is the default network.
5392 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5393 mCellNetworkAgent.connect(true);
5394
5395 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5396 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5397 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5398 vpnNetworkAgent);
5399
5400 // Connect to WiFi; WiFi is the new default.
5401 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5402 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5403 mWiFiNetworkAgent.connect(true);
5404
5405 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5406 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5407 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5408 vpnNetworkAgent);
5409
5410 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5411 // the capabilities.
5412 mCellNetworkAgent.disconnect();
5413
5414 // Disconnect wifi too. Now we have no default network.
5415 mWiFiNetworkAgent.disconnect();
5416
5417 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5418 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5419 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5420 vpnNetworkAgent);
5421
5422 mMockVpn.disconnect();
5423 }
5424
5425 @Test
Varun Anandc51b06d2019-02-25 17:22:02 -08005426 public void testIsActiveNetworkMeteredOverWifi() {
5427 // Returns true by default when no network is available.
5428 assertTrue(mCm.isActiveNetworkMetered());
5429 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5430 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5431 mWiFiNetworkAgent.connect(true);
5432 waitForIdle();
5433
5434 assertFalse(mCm.isActiveNetworkMetered());
5435 }
5436
5437 @Test
5438 public void testIsActiveNetworkMeteredOverCell() {
5439 // Returns true by default when no network is available.
5440 assertTrue(mCm.isActiveNetworkMetered());
5441 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5442 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5443 mCellNetworkAgent.connect(true);
5444 waitForIdle();
5445
5446 assertTrue(mCm.isActiveNetworkMetered());
5447 }
5448
5449 @Test
5450 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
5451 // Returns true by default when no network is available.
5452 assertTrue(mCm.isActiveNetworkMetered());
5453 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5454 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5455 mCellNetworkAgent.connect(true);
5456 waitForIdle();
5457 assertTrue(mCm.isActiveNetworkMetered());
5458
5459 // Connect VPN network. By default it is using current default network (Cell).
5460 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5461 final ArraySet<UidRange> ranges = new ArraySet<>();
5462 final int uid = Process.myUid();
5463 ranges.add(new UidRange(uid, uid));
5464 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5465 mMockVpn.setUids(ranges);
5466 vpnNetworkAgent.connect(true);
5467 mMockVpn.connect();
5468 waitForIdle();
5469 // Ensure VPN is now the active network.
5470 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5471
5472 // Expect VPN to be metered.
5473 assertTrue(mCm.isActiveNetworkMetered());
5474
5475 // Connect WiFi.
5476 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5477 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5478 mWiFiNetworkAgent.connect(true);
5479 waitForIdle();
5480 // VPN should still be the active network.
5481 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5482
5483 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5484 assertFalse(mCm.isActiveNetworkMetered());
5485
5486 // Disconnecting Cell should not affect VPN's meteredness.
5487 mCellNetworkAgent.disconnect();
5488 waitForIdle();
5489
5490 assertFalse(mCm.isActiveNetworkMetered());
5491
5492 // Disconnect WiFi; Now there is no platform default network.
5493 mWiFiNetworkAgent.disconnect();
5494 waitForIdle();
5495
5496 // VPN without any underlying networks is treated as metered.
5497 assertTrue(mCm.isActiveNetworkMetered());
5498
5499 vpnNetworkAgent.disconnect();
5500 mMockVpn.disconnect();
5501 }
5502
5503 @Test
5504 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
5505 // Returns true by default when no network is available.
5506 assertTrue(mCm.isActiveNetworkMetered());
5507 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5508 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5509 mCellNetworkAgent.connect(true);
5510 waitForIdle();
5511 assertTrue(mCm.isActiveNetworkMetered());
5512
5513 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5514 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5515 mWiFiNetworkAgent.connect(true);
5516 waitForIdle();
5517 assertFalse(mCm.isActiveNetworkMetered());
5518
5519 // Connect VPN network.
5520 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5521 final ArraySet<UidRange> ranges = new ArraySet<>();
5522 final int uid = Process.myUid();
5523 ranges.add(new UidRange(uid, uid));
5524 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5525 mMockVpn.setUids(ranges);
5526 vpnNetworkAgent.connect(true);
5527 mMockVpn.connect();
5528 waitForIdle();
5529 // Ensure VPN is now the active network.
5530 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5531 // VPN is using Cell
5532 mService.setUnderlyingNetworksForVpn(
5533 new Network[] { mCellNetworkAgent.getNetwork() });
5534 waitForIdle();
5535
5536 // Expect VPN to be metered.
5537 assertTrue(mCm.isActiveNetworkMetered());
5538
5539 // VPN is now using WiFi
5540 mService.setUnderlyingNetworksForVpn(
5541 new Network[] { mWiFiNetworkAgent.getNetwork() });
5542 waitForIdle();
5543
5544 // Expect VPN to be unmetered
5545 assertFalse(mCm.isActiveNetworkMetered());
5546
5547 // VPN is using Cell | WiFi.
5548 mService.setUnderlyingNetworksForVpn(
5549 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5550 waitForIdle();
5551
5552 // Expect VPN to be metered.
5553 assertTrue(mCm.isActiveNetworkMetered());
5554
5555 // VPN is using WiFi | Cell.
5556 mService.setUnderlyingNetworksForVpn(
5557 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5558 waitForIdle();
5559
5560 // Order should not matter and VPN should still be metered.
5561 assertTrue(mCm.isActiveNetworkMetered());
5562
5563 // VPN is not using any underlying networks.
5564 mService.setUnderlyingNetworksForVpn(new Network[0]);
5565 waitForIdle();
5566
5567 // VPN without underlying networks is treated as metered.
5568 assertTrue(mCm.isActiveNetworkMetered());
5569
5570 vpnNetworkAgent.disconnect();
5571 mMockVpn.disconnect();
5572 }
5573
5574 @Test
5575 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
5576 // Returns true by default when no network is available.
5577 assertTrue(mCm.isActiveNetworkMetered());
5578 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5579 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5580 mWiFiNetworkAgent.connect(true);
5581 waitForIdle();
5582 assertFalse(mCm.isActiveNetworkMetered());
5583
5584 // Connect VPN network.
5585 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5586 final ArraySet<UidRange> ranges = new ArraySet<>();
5587 final int uid = Process.myUid();
5588 ranges.add(new UidRange(uid, uid));
5589 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5590 mMockVpn.setUids(ranges);
5591 vpnNetworkAgent.connect(true);
5592 mMockVpn.connectAsAlwaysMetered();
5593 waitForIdle();
5594 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5595
5596 // VPN is tracking current platform default (WiFi).
5597 mService.setUnderlyingNetworksForVpn(null);
5598 waitForIdle();
5599
5600 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5601 assertTrue(mCm.isActiveNetworkMetered());
5602
5603 // VPN explicitly declares WiFi as its underlying network.
5604 mService.setUnderlyingNetworksForVpn(
5605 new Network[] { mWiFiNetworkAgent.getNetwork() });
5606 waitForIdle();
5607
5608 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5609 assertTrue(mCm.isActiveNetworkMetered());
5610
5611 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5612 // anyways suppose to be metered.
5613 mWiFiNetworkAgent.disconnect();
5614 waitForIdle();
5615
5616 assertTrue(mCm.isActiveNetworkMetered());
5617
5618 vpnNetworkAgent.disconnect();
5619 }
5620
5621 @Test
Mike Yuf9729752018-08-17 15:22:05 +08005622 public void testNetworkBlockedStatus() {
5623 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5624 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5625 .addTransportType(TRANSPORT_CELLULAR)
5626 .build();
5627 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5628
5629 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5630 mCellNetworkAgent.connect(true);
5631 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5632
5633 mService.setUidRulesChanged(RULE_REJECT_ALL);
5634 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5635
5636 // ConnectivityService should cache it not to invoke the callback again.
5637 mService.setUidRulesChanged(RULE_REJECT_METERED);
5638 cellNetworkCallback.assertNoCallback();
5639
5640 mService.setUidRulesChanged(RULE_NONE);
5641 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5642
5643 mService.setUidRulesChanged(RULE_REJECT_METERED);
5644 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5645
5646 // Restrict the network based on UID rule and NOT_METERED capability change.
5647 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5648 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5649 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5650 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5651 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5652 mCellNetworkAgent);
5653 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5654 mService.setUidRulesChanged(RULE_ALLOW_METERED);
5655 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5656
5657 mService.setUidRulesChanged(RULE_NONE);
5658 cellNetworkCallback.assertNoCallback();
5659
5660 // Restrict the network based on BackgroundRestricted.
5661 mService.setRestrictBackgroundChanged(true);
5662 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5663 mService.setRestrictBackgroundChanged(true);
5664 cellNetworkCallback.assertNoCallback();
5665 mService.setRestrictBackgroundChanged(false);
5666 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5667 cellNetworkCallback.assertNoCallback();
5668
5669 mCm.unregisterNetworkCallback(cellNetworkCallback);
5670 }
5671
5672 @Test
5673 public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5674 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5675 mCm.registerDefaultNetworkCallback(defaultCallback);
5676
5677 // No Networkcallbacks invoked before any network is active.
5678 mService.setUidRulesChanged(RULE_REJECT_ALL);
5679 mService.setUidRulesChanged(RULE_NONE);
5680 mService.setUidRulesChanged(RULE_REJECT_METERED);
5681 defaultCallback.assertNoCallback();
5682
5683 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5684 mCellNetworkAgent.connect(true);
5685 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5686 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5687
5688 // Allow to use the network after switching to NOT_METERED network.
5689 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5690 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5691 mWiFiNetworkAgent.connect(true);
5692 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5693
5694 // Switch to METERED network. Restrict the use of the network.
5695 mWiFiNetworkAgent.disconnect();
5696 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5697 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5698
5699 // Network becomes NOT_METERED.
5700 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5701 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5702 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5703
5704 // Verify there's no Networkcallbacks invoked after data saver on/off.
5705 mService.setRestrictBackgroundChanged(true);
5706 mService.setRestrictBackgroundChanged(false);
5707 defaultCallback.assertNoCallback();
5708
5709 mCellNetworkAgent.disconnect();
5710 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5711 defaultCallback.assertNoCallback();
5712
5713 mCm.unregisterNetworkCallback(defaultCallback);
5714 }
5715
junyulai4a192e22018-06-13 15:00:37 +08005716 /**
5717 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5718 */
5719 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5720 InterfaceConfiguration cfg = new InterfaceConfiguration();
5721 cfg.setHardwareAddress("11:22:33:44:55:66");
5722 cfg.setLinkAddress(la);
5723 return cfg;
5724 }
5725
5726 /**
5727 * Make expected stack link properties, copied from Nat464Xlat.
5728 */
5729 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5730 LinkAddress clatAddress = la;
5731 LinkProperties stacked = new LinkProperties();
5732 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5733 RouteInfo ipv4Default = new RouteInfo(
5734 new LinkAddress(Inet4Address.ANY, 0),
5735 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5736 stacked.addRoute(ipv4Default);
5737 stacked.addLinkAddress(clatAddress);
5738 return stacked;
5739 }
5740
5741 @Test
5742 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
5743 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5744 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005745 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5746 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5747
junyulai4a192e22018-06-13 15:00:37 +08005748 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5749 .addTransportType(TRANSPORT_CELLULAR)
5750 .addCapability(NET_CAPABILITY_INTERNET)
5751 .build();
5752 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5753 mCm.registerNetworkCallback(networkRequest, networkCallback);
5754
Lorenzo Colittid593e292019-02-19 13:21:56 +09005755 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005756 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005757 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005758 final LinkProperties cellLp = new LinkProperties();
5759 cellLp.setInterfaceName(MOBILE_IFNAME);
5760 cellLp.addLinkAddress(myIpv6);
5761 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5762 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5763 reset(mNetworkManagementService);
5764 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5765 .thenReturn(getClatInterfaceConfig(myIpv4));
5766
Lorenzo Colittid593e292019-02-19 13:21:56 +09005767 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005768 mCellNetworkAgent.sendLinkProperties(cellLp);
5769 mCellNetworkAgent.connect(true);
5770 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005771 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005772
Lorenzo Colittid593e292019-02-19 13:21:56 +09005773 // Switching default network updates TCP buffer sizes.
5774 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5775
5776 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5777 // the NAT64 prefix was removed because one was never discovered.
5778 cellLp.addLinkAddress(myIpv4);
5779 mCellNetworkAgent.sendLinkProperties(cellLp);
5780 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5781 verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
5782
5783 verifyNoMoreInteractions(mMockNetd);
5784 reset(mMockNetd);
5785
5786 // Remove IPv4 address. Expect prefix discovery to be started again.
5787 cellLp.removeLinkAddress(myIpv4);
5788 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5789 mCellNetworkAgent.sendLinkProperties(cellLp);
5790 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5791 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
5792
5793 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005794 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
5795 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005796 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5797 kNat64PrefixString, 96);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005798 LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
5799 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
5800 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5801 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5802 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5803
5804 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005805 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005806 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005807 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5808 .getStackedLinks();
5809 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5810
5811 // Change trivial linkproperties and see if stacked link is preserved.
5812 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5813 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005814 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5815
5816 List<LinkProperties> stackedLpsAfterChange =
5817 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5818 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5819 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5820
Lorenzo Colittid593e292019-02-19 13:21:56 +09005821 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5822 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005823 cellLp.addLinkAddress(myIpv4);
5824 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5825 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005826 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005827 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005828 verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005829
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005830 // As soon as stop is called, the linkproperties lose the stacked interface.
junyulai4a192e22018-06-13 15:00:37 +08005831 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5832 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005833 LinkProperties expected = new LinkProperties(cellLp);
5834 expected.setNat64Prefix(kNat64Prefix);
5835 assertEquals(expected, actualLpAfterIpv4);
5836 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
junyulai4a192e22018-06-13 15:00:37 +08005837
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005838 // The interface removed callback happens but has no effect after stop is called.
5839 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5840 networkCallback.assertNoCallback();
5841
Lorenzo Colittid593e292019-02-19 13:21:56 +09005842 verifyNoMoreInteractions(mMockNetd);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005843 reset(mMockNetd);
5844
Lorenzo Colittid593e292019-02-19 13:21:56 +09005845 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5846 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5847 kNat64PrefixString, 96);
5848 networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
5849 mCellNetworkAgent);
5850
5851 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005852 cellLp.removeLinkAddress(myIpv4);
5853 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5854 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5855 mCellNetworkAgent.sendLinkProperties(cellLp);
5856 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005857 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
5858 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5859 kNat64PrefixString, 96);
5860 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005861 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5862
Lorenzo Colittid593e292019-02-19 13:21:56 +09005863
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005864 // Clat iface comes up. Expect stacked link to be added.
5865 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005866 networkCallback.expectLinkPropertiesLike(
5867 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005868 mCellNetworkAgent);
5869
5870 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005871 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5872 kNat64PrefixString, 96);
5873 networkCallback.expectLinkPropertiesLike(
5874 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005875 mCellNetworkAgent);
5876 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
5877 networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
5878 mCellNetworkAgent);
5879
5880 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005881 mCellNetworkAgent.disconnect();
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005882 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5883 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005884 mCm.unregisterNetworkCallback(networkCallback);
5885 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005886
5887 @Test
5888 public void testDataActivityTracking() throws RemoteException {
5889 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5890 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5891 .addCapability(NET_CAPABILITY_INTERNET)
5892 .build();
5893 mCm.registerNetworkCallback(networkRequest, networkCallback);
5894
5895 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5896 final LinkProperties cellLp = new LinkProperties();
5897 cellLp.setInterfaceName(MOBILE_IFNAME);
5898 mCellNetworkAgent.sendLinkProperties(cellLp);
5899 reset(mNetworkManagementService);
5900 mCellNetworkAgent.connect(true);
5901 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5902 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5903 eq(ConnectivityManager.TYPE_MOBILE));
5904
5905 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5906 final LinkProperties wifiLp = new LinkProperties();
5907 wifiLp.setInterfaceName(WIFI_IFNAME);
5908 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5909
5910 // Network switch
5911 reset(mNetworkManagementService);
5912 mWiFiNetworkAgent.connect(true);
5913 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5914 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
5915 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5916 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
5917 eq(ConnectivityManager.TYPE_WIFI));
5918 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
5919
5920 // Disconnect wifi and switch back to cell
5921 reset(mNetworkManagementService);
5922 mWiFiNetworkAgent.disconnect();
5923 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5924 assertNoCallbacks(networkCallback);
5925 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5926 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5927 eq(ConnectivityManager.TYPE_MOBILE));
5928
5929 // reconnect wifi
5930 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5931 wifiLp.setInterfaceName(WIFI_IFNAME);
5932 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5933 mWiFiNetworkAgent.connect(true);
5934 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5935 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
5936 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5937
5938 // Disconnect cell
5939 reset(mNetworkManagementService);
5940 mCellNetworkAgent.disconnect();
5941 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5942 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
5943 // sent as network being switched. Ensure rule removal for cell will not be triggered
5944 // unexpectedly before network being removed.
5945 waitForIdle();
5946 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
5947 verify(mNetworkManagementService, times(1)).removeNetwork(
5948 eq(mCellNetworkAgent.getNetwork().netId));
5949
5950 // Disconnect wifi
5951 ConditionVariable cv = waitForConnectivityBroadcasts(1);
5952 reset(mNetworkManagementService);
5953 mWiFiNetworkAgent.disconnect();
5954 waitFor(cv);
5955 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5956
5957 // Clean up
5958 mCm.unregisterNetworkCallback(networkCallback);
5959 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005960
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005961 private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005962 String[] values = tcpBufferSizes.split(",");
5963 String rmemValues = String.join(" ", values[0], values[1], values[2]);
5964 String wmemValues = String.join(" ", values[3], values[4], values[5]);
5965 waitForIdle();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005966 try {
5967 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
5968 } catch (RemoteException e) {
5969 fail("mMockNetd should never throw RemoteException");
5970 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005971 reset(mMockNetd);
5972 }
5973
5974 @Test
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005975 public void testTcpBufferReset() {
5976 final String testTcpBufferSizes = "1,2,3,4,5,6";
5977
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005978 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5979 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005980 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005981 mCellNetworkAgent.connect(false);
5982 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5983
5984 // Change link Properties should have updated tcp buffer size.
5985 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005986 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005987 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005988 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005989 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005990
5991 @Test
5992 public void testGetGlobalProxyForNetwork() {
5993 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5994 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5995 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5996 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
5997 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
5998 }
5999
6000 @Test
6001 public void testGetProxyForActiveNetwork() {
6002 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6003 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6004 mWiFiNetworkAgent.connect(true);
6005 waitForIdle();
6006 assertNull(mService.getProxyForNetwork(null));
6007
6008 final LinkProperties testLinkProperties = new LinkProperties();
6009 testLinkProperties.setHttpProxy(testProxyInfo);
6010
6011 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6012 waitForIdle();
6013
6014 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6015 }
6016
6017 @Test
6018 public void testGetProxyForVPN() {
6019 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6020
6021 // Set up a WiFi network with no proxy
6022 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6023 mWiFiNetworkAgent.connect(true);
6024 waitForIdle();
6025 assertNull(mService.getProxyForNetwork(null));
6026
6027 // Set up a VPN network with a proxy
6028 final int uid = Process.myUid();
6029 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
6030 final ArraySet<UidRange> ranges = new ArraySet<>();
6031 ranges.add(new UidRange(uid, uid));
6032 mMockVpn.setUids(ranges);
6033 LinkProperties testLinkProperties = new LinkProperties();
6034 testLinkProperties.setHttpProxy(testProxyInfo);
6035 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6036 waitForIdle();
6037
6038 // Connect to VPN with proxy
6039 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6040 vpnNetworkAgent.connect(true);
6041 mMockVpn.connect();
6042 waitForIdle();
6043
6044 // Test that the VPN network returns a proxy, and the WiFi does not.
6045 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6046 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6047 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6048
6049 // Test that the VPN network returns no proxy when it is set to null.
6050 testLinkProperties.setHttpProxy(null);
6051 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6052 waitForIdle();
6053 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6054 assertNull(mService.getProxyForNetwork(null));
6055
6056 // Set WiFi proxy and check that the vpn proxy is still null.
6057 testLinkProperties.setHttpProxy(testProxyInfo);
6058 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6059 waitForIdle();
6060 assertNull(mService.getProxyForNetwork(null));
6061
6062 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6063 // correct proxy setting.
6064 vpnNetworkAgent.disconnect();
6065 waitForIdle();
6066 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6067 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6068 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6069 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006070}