blob: eb6c1d8be903cacda75d2da9e6c608342e266dc6 [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
Rubin Xu9e64dc02019-04-23 18:04:14 +010019import static android.content.pm.PackageManager.GET_PERMISSIONS;
20import static android.content.pm.PackageManager.MATCH_ANY_USER;
Erik Klinef851d6d2015-04-20 16:03:48 +090021import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090022import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070023import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
24import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
25import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090026import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070027import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090028import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
29import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Hugo Benichi16f0a942017-06-20 14:07:59 +090030import static android.net.ConnectivityManager.TYPE_NONE;
Lorenzo Colitti80986d92019-03-22 00:28:28 +090031import static android.net.ConnectivityManager.TYPE_VPN;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070032import static android.net.ConnectivityManager.TYPE_WIFI;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090033import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
lucasline252a742019-03-12 13:08:03 +080034import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090035import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060036import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
38import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
44import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
45import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
46import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
47import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090048import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060049import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080050import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060051import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
52import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
53import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
54import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
55import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
57import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
58import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090059import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060060import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
61import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080062import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
63import static android.net.NetworkPolicyManager.RULE_NONE;
64import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
65import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000066import static android.net.RouteInfo.RTN_UNREACHABLE;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060067
68import static com.android.internal.util.TestUtils.waitForIdleHandler;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090069import static com.android.internal.util.TestUtils.waitForIdleLooper;
junyulai7c469172019-01-16 20:23:34 +080070import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090071
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000072import static org.junit.Assert.assertArrayEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090073import static org.junit.Assert.assertEquals;
74import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080075import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090076import static org.junit.Assert.assertNotNull;
77import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060078import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090079import static org.junit.Assert.fail;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000080import static org.mockito.ArgumentMatchers.eq;
Erik Klinee89953b2018-01-11 16:11:10 +090081import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +090082import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060083import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090084import static org.mockito.Mockito.doAnswer;
85import static org.mockito.Mockito.doNothing;
Erik Kline117e7f32018-03-04 21:01:01 +090086import static org.mockito.Mockito.eq;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000087import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080088import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060089import static org.mockito.Mockito.never;
90import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090091import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090092import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +090093import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060094import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -070095import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090096import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070097
junyulai7c469172019-01-16 20:23:34 +080098import android.annotation.NonNull;
Lorenzo Colitti73b209382016-09-15 22:18:09 +090099import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400100import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400101import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900102import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900103import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700104import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400105import android.content.Intent;
106import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000107import android.content.pm.ApplicationInfo;
108import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100109import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000110import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900111import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400112import android.net.ConnectivityManager;
113import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900114import android.net.ConnectivityManager.PacketKeepalive;
115import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900116import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900117import android.net.ConnectivityThread;
Luke Huang65914772019-03-16 00:31:46 +0800118import android.net.IDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800119import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900120import android.net.INetworkMonitor;
121import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800122import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700123import android.net.INetworkPolicyManager;
124import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800125import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900126import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800127import android.net.IpSecManager;
128import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900129import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700130import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700131import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400132import android.net.Network;
133import android.net.NetworkAgent;
134import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700135import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700136import android.net.NetworkInfo;
137import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400138import android.net.NetworkMisc;
139import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700140import android.net.NetworkSpecifier;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900141import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800142import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100143import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000144import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800145import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700146import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800147import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900148import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900149import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900150import android.net.shared.NetworkMonitorUtils;
151import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900152import android.net.util.MultinetworkPolicyTracker;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100153import android.os.Binder;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400154import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700155import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700156import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700157import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900158import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900159import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700160import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800161import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700162import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000163import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800164import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900165import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900166import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000167import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900168import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800169import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900170import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800171import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100172import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700173import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800174import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700175
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800176import androidx.test.InstrumentationRegistry;
177import androidx.test.filters.SmallTest;
178import androidx.test.runner.AndroidJUnit4;
179
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900180import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800181import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900182import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900183import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900184import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900185import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900186import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900187import com.android.server.connectivity.DefaultNetworkMetrics;
188import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900189import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800190import com.android.server.connectivity.Nat464Xlat;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000191import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800192import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900193import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900194import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900195import com.android.server.net.NetworkPolicyManagerInternal;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400196
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900197import org.junit.After;
198import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900199import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900200import org.junit.Test;
201import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900202import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000203import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900204import org.mockito.Mock;
205import org.mockito.MockitoAnnotations;
206import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900207import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900208
junyulai0c666972019-03-04 22:45:36 +0800209import java.io.IOException;
210import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800211import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000212import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700213import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900214import java.net.InetSocketAddress;
215import java.net.Socket;
junyulai4a192e22018-06-13 15:00:37 +0800216import java.net.UnknownHostException;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400217import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900218import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100219import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800220import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500221import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100222import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900223import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100224import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900225import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800226import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800227import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800228import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900229import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900230import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700231import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900232import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700233
234/**
235 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400236 *
237 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900238 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700239 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900240@RunWith(AndroidJUnit4.class)
241@SmallTest
242public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700243 private static final String TAG = "ConnectivityServiceTest";
244
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900245 private static final int TIMEOUT_MS = 500;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900246 private static final int TEST_LINGER_DELAY_MS = 250;
247 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
248 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
249 // timeout. For this, our assertions should run fast enough to leave less than
250 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
251 // supposedly fired, and the time we call expectCallback.
252 private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900253 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
254 // complete before callbacks are verified.
255 private final static int TEST_REQUEST_TIMEOUT_MS = 150;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900256
junyulai4a192e22018-06-13 15:00:37 +0800257 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700258 private static final String MOBILE_IFNAME = "test_rmnet_data0";
259 private static final String WIFI_IFNAME = "test_wlan0";
Luke Huang65914772019-03-16 00:31:46 +0800260 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700261
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900262 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400263 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900264 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400265 private MockNetworkAgent mWiFiNetworkAgent;
266 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900267 private MockNetworkAgent mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900268 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900269 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800270 private INetworkPolicyListener mPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700271
Hugo Benichi64901e52017-10-19 14:42:40 +0900272 @Mock IpConnectivityMetrics.Logger mMetricsService;
273 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900274 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600275 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800276 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800277 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800278 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900279 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100280 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000281 @Mock UserManager mUserManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900282
waynema13516842019-03-12 18:13:49 +0800283 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
284 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900285
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900286 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
287 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
288 // reflect the state of our test ConnectivityService.
289 private class WrappedConnectivityManager extends ConnectivityManager {
290 private Network mFakeBoundNetwork;
291
292 public synchronized boolean bindProcessToNetwork(Network network) {
293 mFakeBoundNetwork = network;
294 return true;
295 }
296
297 public synchronized Network getBoundNetworkForProcess() {
298 return mFakeBoundNetwork;
299 }
300
301 public WrappedConnectivityManager(Context context, ConnectivityService service) {
302 super(context, service);
303 }
304 }
305
Paul Jensend7b6ca92015-05-13 14:05:12 -0400306 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900307 private final MockContentResolver mContentResolver;
308
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900309 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900310 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900311
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900312 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400313 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900314
315 mResources = spy(base.getResources());
316 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
317 thenReturn(new String[] {
318 "wifi,1,1,1,-1,true",
319 "mobile,0,0,0,-1,true",
320 "mobile_mms,2,0,2,60000,true",
321 });
322
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900323 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900324 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400325 }
326
327 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900328 public void startActivityAsUser(Intent intent, UserHandle handle) {
329 mStartedActivities.offer(intent);
330 }
331
332 public Intent expectStartActivityIntent(int timeoutMs) {
333 Intent intent = null;
334 try {
335 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
336 } catch (InterruptedException e) {}
337 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
338 return intent;
339 }
340
341 public void expectNoStartActivityIntent(int timeoutMs) {
342 try {
343 assertNull("Received unexpected Intent to start activity",
344 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
345 } catch (InterruptedException e) {}
346 }
347
348 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900349 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900350 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
351 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900352 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000353 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400354 return super.getSystemService(name);
355 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900356
357 @Override
358 public ContentResolver getContentResolver() {
359 return mContentResolver;
360 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900361
362 @Override
363 public Resources getResources() {
364 return mResources;
365 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100366
367 @Override
368 public PackageManager getPackageManager() {
369 return mPackageManager;
370 }
371 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400372
Hugo Benichi669f0232017-06-29 22:58:39 +0900373 public void waitForIdle(int timeoutMsAsInt) {
374 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900375 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
376 waitForIdle(mCellNetworkAgent, timeoutMs);
377 waitForIdle(mWiFiNetworkAgent, timeoutMs);
378 waitForIdle(mEthernetNetworkAgent, timeoutMs);
379 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900380 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900381 }
382
Hugo Benichi669f0232017-06-29 22:58:39 +0900383 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900384 if (agent == null) {
385 return;
386 }
387 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
388 }
389
390 private void waitForIdle() {
391 waitForIdle(TIMEOUT_MS);
392 }
393
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900394 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900395 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900396 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
397
398 // Tests that waitForIdle returns immediately if the service is already idle.
399 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900400 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900401 }
402
403 // Bring up a network that we can use to send messages to ConnectivityService.
404 ConditionVariable cv = waitForConnectivityBroadcasts(1);
405 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
406 mWiFiNetworkAgent.connect(false);
407 waitFor(cv);
408 Network n = mWiFiNetworkAgent.getNetwork();
409 assertNotNull(n);
410
411 // Tests that calling waitForIdle waits for messages to be processed.
412 for (int i = 0; i < attempts; i++) {
413 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900414 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900415 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
416 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900417 }
418
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900419 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
420 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800421 @Ignore
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900422 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900423 // Bring up a network that we can use to send messages to ConnectivityService.
424 ConditionVariable cv = waitForConnectivityBroadcasts(1);
425 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
426 mWiFiNetworkAgent.connect(false);
427 waitFor(cv);
428 Network n = mWiFiNetworkAgent.getNetwork();
429 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900430
431 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900432 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900433 for (int i = 0; i < attempts; i++) {
434 mWiFiNetworkAgent.setSignalStrength(i);
435 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
436 // We hit a race condition, as expected. Pass the test.
437 return;
438 }
439 }
440
441 // No race? There is a bug in this test.
442 fail("expected race condition at least once in " + attempts + " attempts");
443 }
444
Paul Jensend7b6ca92015-05-13 14:05:12 -0400445 private class MockNetworkAgent {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900446 private final INetworkMonitor mNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400447 private final NetworkInfo mNetworkInfo;
448 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900449 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400450 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400451 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700452 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400453 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400454 private NetworkAgent mNetworkAgent;
junyulai0c666972019-03-04 22:45:36 +0800455 private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
junyulai48eac1d42018-12-27 17:25:29 +0800456 private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900457 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400458 // Contains the redirectUrl from networkStatus(). Before reading, wait for
459 // mNetworkStatusReceived.
460 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400461
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900462 private INetworkMonitorCallbacks mNmCallbacks;
463 private int mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
464 private String mNmValidationRedirectUrl = null;
465 private boolean mNmProvNotificationRequested = false;
466
467 void setNetworkValid() {
468 mNmValidationResult = NETWORK_TEST_RESULT_VALID;
469 mNmValidationRedirectUrl = null;
470 }
471
472 void setNetworkInvalid() {
473 mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
474 mNmValidationRedirectUrl = null;
475 }
476
477 void setNetworkPortal(String redirectUrl) {
478 setNetworkInvalid();
479 mNmValidationRedirectUrl = redirectUrl;
480 }
481
lucasline252a742019-03-12 13:08:03 +0800482 void setNetworkPartial() {
483 mNmValidationResult = NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
484 mNmValidationRedirectUrl = null;
485 }
486
Paul Jensend7b6ca92015-05-13 14:05:12 -0400487 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100488 this(transport, new LinkProperties());
489 }
490
491 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400492 final int type = transportToLegacyType(transport);
Lorenzo Colitti80986d92019-03-22 00:28:28 +0900493 final String typeName = ConnectivityManager.getNetworkTypeName(type);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400494 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
495 mNetworkCapabilities = new NetworkCapabilities();
496 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400497 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900498 case TRANSPORT_ETHERNET:
499 mScore = 70;
500 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400501 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400502 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400503 break;
504 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400505 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400506 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900507 case TRANSPORT_WIFI_AWARE:
508 mScore = 20;
509 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900510 case TRANSPORT_VPN:
Chalard Jeanb552c462018-02-21 18:43:54 +0900511 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
Chalard Jeandda156a2018-01-10 21:19:32 +0900512 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
Chalard Jean0b214af2018-01-12 17:22:49 +0900513 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400514 default:
515 throw new UnsupportedOperationException("unimplemented network type");
516 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900517 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900518 mHandlerThread.start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900519
520 mNetworkMonitor = mock(INetworkMonitor.class);
521 final Answer validateAnswer = inv -> {
522 new Thread(this::onValidationRequested).start();
523 return null;
524 };
525
526 try {
Remi NGUYEN VAN3962f672019-03-27 15:42:53 +0900527 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900528 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
529 } catch (RemoteException e) {
530 fail(e.getMessage());
531 }
532
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900533 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900534 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
535 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
536 doNothing().when(mNetworkStack).makeNetworkMonitor(
537 nmNetworkCaptor.capture(),
538 any() /* name */,
539 nmCbCaptor.capture());
540
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900541 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
542 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Chalard Jean05ab6812018-05-02 21:14:54 +0900543 linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900544 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900545 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900546
547 @Override
junyulai06835112019-01-03 18:50:15 +0800548 public void startSocketKeepalive(Message msg) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900549 int slot = msg.arg1;
550 if (mExpectedKeepaliveSlot != null) {
551 assertEquals((int) mExpectedKeepaliveSlot, slot);
552 }
junyulai06835112019-01-03 18:50:15 +0800553 onSocketKeepaliveEvent(slot, mStartKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900554 }
555
556 @Override
junyulai06835112019-01-03 18:50:15 +0800557 public void stopSocketKeepalive(Message msg) {
558 onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900559 }
Paul Jensen232437312016-04-06 09:51:26 -0400560
561 @Override
562 public void networkStatus(int status, String redirectUrl) {
563 mRedirectUrl = redirectUrl;
564 mNetworkStatusReceived.open();
565 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700566
567 @Override
568 protected void preventAutomaticReconnect() {
569 mPreventReconnectReceived.open();
570 }
Aaron Huang9eeaa3a2019-04-19 22:47:26 +0800571
572 @Override
573 protected void addKeepalivePacketFilter(Message msg) {
574 Log.i(TAG, "Add keepalive packet filter.");
575 }
576
577 @Override
578 protected void removeKeepalivePacketFilter(Message msg) {
579 Log.i(TAG, "Remove keepalive packet filter.");
580 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400581 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900582
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900583 assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900584 mNmCallbacks = nmCbCaptor.getValue();
585
586 try {
587 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
588 } catch (RemoteException e) {
589 fail(e.getMessage());
590 }
591
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900592 // Waits for the NetworkAgent to be registered, which includes the creation of the
593 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900594 waitForIdle();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900595 }
596
597 private void onValidationRequested() {
598 try {
599 if (mNmProvNotificationRequested
600 && mNmValidationResult == NETWORK_TEST_RESULT_VALID) {
601 mNmCallbacks.hideProvisioningNotification();
602 mNmProvNotificationRequested = false;
603 }
604
605 mNmCallbacks.notifyNetworkTested(
606 mNmValidationResult, mNmValidationRedirectUrl);
607
608 if (mNmValidationRedirectUrl != null) {
609 mNmCallbacks.showProvisioningNotification(
Remi NGUYEN VAN9c5d9642019-02-07 21:29:57 +0900610 "test_provisioning_notif_action", "com.android.test.package");
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900611 mNmProvNotificationRequested = true;
612 }
613 } catch (RemoteException e) {
614 fail(e.getMessage());
615 }
Paul Jensen3d911462015-06-12 06:40:24 -0400616 }
617
618 public void adjustScore(int change) {
619 mScore += change;
620 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400621 }
622
Lorenzo Colitti80986d92019-03-22 00:28:28 +0900623 public int getScore() {
624 return mScore;
625 }
626
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900627 public void explicitlySelected(boolean acceptUnvalidated) {
628 mNetworkAgent.explicitlySelected(acceptUnvalidated);
629 }
630
Paul Jensen85cf78e2015-06-25 13:25:07 -0400631 public void addCapability(int capability) {
632 mNetworkCapabilities.addCapability(capability);
633 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
634 }
635
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900636 public void removeCapability(int capability) {
637 mNetworkCapabilities.removeCapability(capability);
638 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
639 }
640
Chalard Jean0b214af2018-01-12 17:22:49 +0900641 public void setUids(Set<UidRange> uids) {
642 mNetworkCapabilities.setUids(uids);
643 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
644 }
645
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900646 public void setSignalStrength(int signalStrength) {
647 mNetworkCapabilities.setSignalStrength(signalStrength);
648 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
649 }
650
Etan Cohena7434272017-04-03 12:17:51 -0700651 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
652 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900653 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
654 }
655
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900656 public void setNetworkCapabilities(NetworkCapabilities nc,
657 boolean sendToConnectivityService) {
658 mNetworkCapabilities.set(nc);
659 if (sendToConnectivityService) {
660 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
661 }
662 }
663
Paul Jensene0988542015-06-25 15:30:08 -0400664 public void connectWithoutInternet() {
665 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
666 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
667 }
668
Paul Jensend7b6ca92015-05-13 14:05:12 -0400669 /**
Paul Jensene0988542015-06-25 15:30:08 -0400670 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400671 * @param validated Indicate if network should pretend to be validated.
672 */
673 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900674 connect(validated, true);
675 }
676
677 /**
678 * Transition this NetworkAgent to CONNECTED state.
679 * @param validated Indicate if network should pretend to be validated.
680 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
681 */
682 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900683 assertEquals("MockNetworkAgents can only be connected once",
684 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400685 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
686
Paul Jensend7b6ca92015-05-13 14:05:12 -0400687 NetworkCallback callback = null;
688 final ConditionVariable validatedCv = new ConditionVariable();
689 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900690 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400691 NetworkRequest request = new NetworkRequest.Builder()
692 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900693 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400694 .build();
695 callback = new NetworkCallback() {
696 public void onCapabilitiesChanged(Network network,
697 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400698 if (network.equals(getNetwork()) &&
699 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400700 validatedCv.open();
701 }
702 }
703 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400704 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400705 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900706 if (hasInternet) {
707 addCapability(NET_CAPABILITY_INTERNET);
708 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400709
Paul Jensene0988542015-06-25 15:30:08 -0400710 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400711
712 if (validated) {
713 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400714 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900715 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400716 }
717
718 if (callback != null) mCm.unregisterNetworkCallback(callback);
719 }
720
Paul Jensen232437312016-04-06 09:51:26 -0400721 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900722 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400723 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400724 }
725
lucasline252a742019-03-12 13:08:03 +0800726 public void connectWithPartialConnectivity() {
727 setNetworkPartial();
728 connect(false);
729 }
730
Erik Kline1d3db322017-02-28 16:20:20 +0900731 public void suspend() {
732 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
733 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
734 }
735
Chalard Jean804b8fb2018-01-30 22:41:41 +0900736 public void resume() {
737 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
738 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
739 }
740
Paul Jensend7b6ca92015-05-13 14:05:12 -0400741 public void disconnect() {
742 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
743 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
744 }
745
746 public Network getNetwork() {
747 return new Network(mNetworkAgent.netId);
748 }
Paul Jensene0988542015-06-25 15:30:08 -0400749
Calvin On1f64f3f2016-10-11 15:10:46 -0700750 public ConditionVariable getPreventReconnectReceived() {
751 return mPreventReconnectReceived;
752 }
753
Paul Jensene0988542015-06-25 15:30:08 -0400754 public ConditionVariable getDisconnectedCV() {
755 return mDisconnected;
756 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400757
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900758 public void sendLinkProperties(LinkProperties lp) {
759 mNetworkAgent.sendLinkProperties(lp);
760 }
761
762 public void setStartKeepaliveError(int error) {
763 mStartKeepaliveError = error;
764 }
765
766 public void setStopKeepaliveError(int error) {
767 mStopKeepaliveError = error;
768 }
769
770 public void setExpectedKeepaliveSlot(Integer slot) {
771 mExpectedKeepaliveSlot = slot;
772 }
Paul Jensen232437312016-04-06 09:51:26 -0400773
774 public String waitForRedirectUrl() {
775 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
776 return mRedirectUrl;
777 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900778
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900779 public NetworkAgent getNetworkAgent() {
780 return mNetworkAgent;
781 }
782
Chalard Jean804b8fb2018-01-30 22:41:41 +0900783 public NetworkCapabilities getNetworkCapabilities() {
784 return mNetworkCapabilities;
785 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400786 }
787
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900788 /**
789 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
790 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900791 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900792 * expectRemoveRequests.
793 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700794 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400795 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
796 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400797 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700798
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900799 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900800 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
801 // once, then cause some other thread to add or remove requests, then call
802 // waitForRequests().
803 // It is not possible to wait for both add and remove requests. When adding, the queue
804 // contains the expected score. When removing, the value is unused, all matters is the
805 // number of objects in the queue.
806 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900807
808 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900809 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900810 private boolean mExpectingAdditions;
811
Etan Cohenddb720a2019-01-08 12:09:18 -0800812 // Used to collect the networks requests managed by this factory. This is a duplicate of
813 // the internal information stored in the NetworkFactory (which is private).
814 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
815
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700816 public MockNetworkFactory(Looper looper, Context context, String logTag,
817 NetworkCapabilities filter) {
818 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900819 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700820 }
821
822 public int getMyRequestCount() {
823 return getRequestCount();
824 }
825
826 protected void startNetwork() {
827 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400828 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700829 }
830
831 protected void stopNetwork() {
832 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400833 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700834 }
835
836 public boolean getMyStartRequested() {
837 return mNetworkStarted.get();
838 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400839
840 public ConditionVariable getNetworkStartedCV() {
841 mNetworkStartedCV.close();
842 return mNetworkStartedCV;
843 }
844
845 public ConditionVariable getNetworkStoppedCV() {
846 mNetworkStoppedCV.close();
847 return mNetworkStoppedCV;
848 }
849
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900850 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900851 protected void handleAddRequest(NetworkRequest request, int score,
852 int factorySerialNumber) {
853 synchronized (mExpectations) {
854 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900855
Chalard Jean05ab6812018-05-02 21:14:54 +0900856 assertNotNull("Added more requests than expected (" + request + " score : "
857 + score + ")", expectedScore);
858 // If we're expecting anything, we must be expecting additions.
859 if (!mExpectingAdditions) {
860 fail("Can't add requests while expecting requests to be removed");
861 }
862 if (expectedScore != score) {
863 fail("Expected score was " + expectedScore + " but actual was " + score
864 + " in added request");
865 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900866
Chalard Jean05ab6812018-05-02 21:14:54 +0900867 // Add the request.
868 mNetworkRequests.put(request.requestId, request);
869 super.handleAddRequest(request, score, factorySerialNumber);
870 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900871 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400872 }
873
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900874 @Override
875 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900876 synchronized (mExpectations) {
877 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900878
Chalard Jean05ab6812018-05-02 21:14:54 +0900879 assertTrue("Removed more requests than expected", expectedScore != null);
880 // If we're expecting anything, we must be expecting removals.
881 if (mExpectingAdditions) {
882 fail("Can't remove requests while expecting requests to be added");
883 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900884
Chalard Jean05ab6812018-05-02 21:14:54 +0900885 // Remove the request.
886 mNetworkRequests.remove(request.requestId);
887 super.handleRemoveRequest(request);
888 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900889 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400890 }
891
Etan Cohenddb720a2019-01-08 12:09:18 -0800892 // Trigger releasing the request as unfulfillable
893 public void triggerUnfulfillable(NetworkRequest r) {
894 super.releaseRequestAsUnfulfillableByAnyFactory(r);
895 }
896
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900897 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900898 if (mExpectations.size() != 0) {
899 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900900 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400901 }
902
Chalard Jean05ab6812018-05-02 21:14:54 +0900903 // Expects that requests with the specified scores will be added.
904 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900905 assertNoExpectations();
906 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900907 for (int score : scores) {
908 mExpectations.add(score);
909 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400910 }
911
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900912 // Expects that count requests will be removed.
913 public void expectRemoveRequests(final int count) {
914 assertNoExpectations();
915 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900916 for (int i = 0; i < count; ++i) {
917 mExpectations.add(0); // For removals the score is ignored so any value will do.
918 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900919 }
920
921 // Waits for the expected request additions or removals to happen within a timeout.
922 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900923 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
924 synchronized (mExpectations) {
925 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
926 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
927 }
928 }
929 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900930 final String msg = count + " requests still not " +
931 (mExpectingAdditions ? "added" : "removed") +
932 " after " + TIMEOUT_MS + " ms";
933 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900934 }
935
Etan Cohenddb720a2019-01-08 12:09:18 -0800936 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
937 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900938 waitForRequests();
939 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800940 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400941 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700942 }
943
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900944 private static Looper startHandlerThreadAndReturnLooper() {
945 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
946 handlerThread.start();
947 return handlerThread.getLooper();
948 }
949
950 private class MockVpn extends Vpn {
951 // TODO : the interactions between this mock and the mock network agent are too
952 // hard to get right at this moment, because it's unclear in which case which
953 // target needs to get a method call or both, and in what order. It's because
954 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
955 // parent class of MockVpn agent wants that responsibility.
956 // That being said inside the test it should be possible to make the interactions
957 // harder to get wrong with precise speccing, judicious comments, helper methods
958 // and a few sprinkled assertions.
959
960 private boolean mConnected = false;
961 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
962 // not inherit from NetworkAgent.
963 private MockNetworkAgent mMockNetworkAgent;
964
965 public MockVpn(int userId) {
966 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
967 userId);
968 }
969
970 public void setNetworkAgent(MockNetworkAgent agent) {
971 waitForIdle(agent, TIMEOUT_MS);
972 mMockNetworkAgent = agent;
973 mNetworkAgent = agent.getNetworkAgent();
974 mNetworkCapabilities.set(agent.getNetworkCapabilities());
975 }
976
977 public void setUids(Set<UidRange> uids) {
978 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800979 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900980 }
981
982 @Override
983 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800984 if (mMockNetworkAgent == null) {
985 return NETID_UNSET;
986 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900987 return mMockNetworkAgent.getNetwork().netId;
988 }
989
990 @Override
991 public boolean appliesToUid(int uid) {
992 return mConnected; // Trickery to simplify testing.
993 }
994
995 @Override
996 protected boolean isCallerEstablishedOwnerLocked() {
997 return mConnected; // Similar trickery
998 }
999
Varun Anandc51b06d2019-02-25 17:22:02 -08001000 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001001 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1002 mConnected = true;
1003 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -08001004 mConfig.isMetered = isAlwaysMetered;
1005 }
1006
1007 public void connectAsAlwaysMetered() {
1008 connect(true /* isAlwaysMetered */);
1009 }
1010
1011 public void connect() {
1012 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001013 }
1014
1015 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001016 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1017 if (!mConnected) return null;
1018 super.updateCapabilities(defaultNetwork);
1019 // Because super.updateCapabilities will update the capabilities of the agent but
1020 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001021 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -08001022 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001023 }
1024
1025 private void copyCapabilitiesToNetworkAgent() {
1026 if (null != mMockNetworkAgent) {
1027 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1028 false /* sendToConnectivityService */);
1029 }
1030 }
1031
1032 public void disconnect() {
1033 mConnected = false;
1034 mConfig = null;
1035 }
1036 }
1037
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001038 private class FakeWakeupMessage extends WakeupMessage {
1039 private static final int UNREASONABLY_LONG_WAIT = 1000;
1040
1041 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
1042 super(context, handler, cmdName, cmd);
1043 }
1044
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001045 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
1046 int arg1, int arg2, Object obj) {
1047 super(context, handler, cmdName, cmd, arg1, arg2, obj);
1048 }
1049
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001050 @Override
1051 public void schedule(long when) {
1052 long delayMs = when - SystemClock.elapsedRealtime();
1053 if (delayMs < 0) delayMs = 0;
1054 if (delayMs > UNREASONABLY_LONG_WAIT) {
1055 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
1056 "ms into the future: " + delayMs);
1057 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001058 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
1059 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001060 }
1061
1062 @Override
1063 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001064 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001065 }
1066
1067 @Override
1068 public void onAlarm() {
1069 throw new AssertionError("Should never happen. Update this fake.");
1070 }
1071 }
1072
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001073 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +09001074 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001075 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -04001076
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001077 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001078 super(c, h, r);
1079 }
1080
1081 @Override
1082 public boolean configRestrictsAvoidBadWifi() {
1083 return configRestrictsAvoidBadWifi;
1084 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001085
1086 @Override
1087 public int configMeteredMultipathPreference() {
1088 return configMeteredMultipathPreference;
1089 }
Erik Kline065ab6e2016-10-02 18:02:14 +09001090 }
1091
1092 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001093 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001094 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +09001095
Paul Jensend7b6ca92015-05-13 14:05:12 -04001096 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001097 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Luke Huang65914772019-03-16 00:31:46 +08001098 IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) {
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001099 super(context, netManager, statsService, policyManager, dnsResolver, log, netd);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001100 mNetd = netd;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001101 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001102 }
1103
1104 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001105 protected MockableSystemProperties getSystemProperties() {
1106 // Minimal approach to overriding system properties: let most calls fall through to real
1107 // device values, and only override ones values that are important to this test.
1108 mSystemProperties = spy(new MockableSystemProperties());
1109 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1110 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1111 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001112 }
Paul Jensen67b0b072015-06-10 11:22:17 -04001113
1114 @Override
Mike Yuf9729752018-08-17 15:22:05 +08001115 protected Tethering makeTethering() {
1116 return mock(Tethering.class);
1117 }
1118
1119 @Override
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001120 protected ProxyTracker makeProxyTracker() {
1121 return mock(ProxyTracker.class);
1122 }
1123
1124 @Override
Paul Jensen67b0b072015-06-10 11:22:17 -04001125 protected int reserveNetId() {
1126 while (true) {
1127 final int netId = super.reserveNetId();
1128
1129 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1130 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001131 Context context = InstrumentationRegistry.getContext();
1132 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -04001133 boolean overlaps = false;
1134 for (Network network : networks) {
1135 if (netId == network.netId) {
1136 overlaps = true;
1137 break;
1138 }
1139 }
1140 if (overlaps) continue;
1141
1142 return netId;
1143 }
1144 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001145
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001146 @Override
1147 protected boolean queryUserAccess(int uid, int netId) {
1148 return true;
1149 }
1150
junyulai4a192e22018-06-13 15:00:37 +08001151 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1152 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1153 }
1154
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001155 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001156 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +09001157 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001158 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +09001159 return tracker;
1160 }
1161
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001162 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1163 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001164 }
1165
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001166 @Override
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +09001167 protected NetworkStackClient getNetworkStack() {
1168 return mNetworkStack;
1169 }
1170
1171 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +09001172 public WakeupMessage makeWakeupMessage(
1173 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1174 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001175 }
1176
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001177 @Override
1178 public boolean hasService(String name) {
1179 // Currenty, the only relevant service that ConnectivityService checks for is
1180 // ETHERNET_SERVICE.
1181 return Context.ETHERNET_SERVICE.equals(name);
1182 }
1183
Hugo Benichi64901e52017-10-19 14:42:40 +09001184 @Override
1185 protected IpConnectivityMetrics.Logger metricsLogger() {
1186 return mMetricsService;
1187 }
1188
dalyk1fcb7392018-03-05 12:42:22 -05001189 @Override
1190 protected void registerNetdEventCallback() {
1191 }
1192
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001193 public void mockVpn(int uid) {
1194 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001195 int userId = UserHandle.getUserId(uid);
1196 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001197 // This has no effect unless the VPN is actually connected, because things like
1198 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1199 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001200 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001201 }
1202 }
1203
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001204 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001205 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001206 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001207
1208 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001209 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001210 }
Mike Yuf9729752018-08-17 15:22:05 +08001211
1212 public void setUidRulesChanged(int uidRules) {
1213 try {
1214 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1215 } catch (RemoteException ignored) {
1216 }
1217 }
1218
1219 public void setRestrictBackgroundChanged(boolean restrictBackground) {
1220 try {
1221 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1222 } catch (RemoteException ignored) {
1223 }
1224 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001225 }
1226
Paul Jensen3d911462015-06-12 06:40:24 -04001227 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001228 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1229 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001230 */
1231 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001232 if (conditionVariable.block(TIMEOUT_MS)) {
1233 return;
1234 }
1235 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001236 }
1237
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001238 private static final int VPN_USER = 0;
1239 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1240 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1241 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1242
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001243 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001244 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001245 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001246
Hugo Benichi64901e52017-10-19 14:42:40 +09001247 MockitoAnnotations.initMocks(this);
1248 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1249
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001250 when(mUserManager.getUsers(eq(true))).thenReturn(
1251 Arrays.asList(new UserInfo[] {
1252 new UserInfo(VPN_USER, "", 0),
1253 }));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001254
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001255 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1256 // http://b/25897652 .
1257 if (Looper.myLooper() == null) {
1258 Looper.prepare();
1259 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001260 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001261
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001262 FakeSettingsProvider.clearSettingsProvider();
1263 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1264 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001265 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1266 LocalServices.addService(
1267 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001268
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001269 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001270 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001271 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001272 mNpm,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001273 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001274 mMockNetd,
1275 mMockDnsResolver);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001276
Mike Yuf9729752018-08-17 15:22:05 +08001277 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1278 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1279 verify(mNpm).registerListener(policyListenerCaptor.capture());
1280 mPolicyListener = policyListenerCaptor.getValue();
1281
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001282 // Create local CM before sending system ready so that we can answer
1283 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001284 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001285 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001286 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001287 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001288
1289 // Ensure that the default setting for Captive Portals is used for most tests
1290 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001291 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001292 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001293 }
1294
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001295 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001296 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001297 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001298 if (mCellNetworkAgent != null) {
1299 mCellNetworkAgent.disconnect();
1300 mCellNetworkAgent = null;
1301 }
1302 if (mWiFiNetworkAgent != null) {
1303 mWiFiNetworkAgent.disconnect();
1304 mWiFiNetworkAgent = null;
1305 }
1306 if (mEthernetNetworkAgent != null) {
1307 mEthernetNetworkAgent.disconnect();
1308 mEthernetNetworkAgent = null;
1309 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001310 FakeSettingsProvider.clearSettingsProvider();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001311 }
1312
Rubin Xu9e64dc02019-04-23 18:04:14 +01001313 private void mockDefaultPackages() throws Exception {
1314 final String testPackageName = mContext.getPackageName();
1315 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1316 testPackageName, PackageManager.GET_PERMISSIONS);
1317 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1318 new String[] {testPackageName});
1319 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1320 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1321
1322 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1323 Arrays.asList(new PackageInfo[] {
1324 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1325 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1326 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1327 }));
1328 }
1329
1330 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001331 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001332 case TRANSPORT_ETHERNET:
1333 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001334 case TRANSPORT_WIFI:
1335 return TYPE_WIFI;
1336 case TRANSPORT_CELLULAR:
1337 return TYPE_MOBILE;
Lorenzo Colitti80986d92019-03-22 00:28:28 +09001338 case TRANSPORT_VPN:
1339 return TYPE_VPN;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001340 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001341 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001342 }
1343 }
1344
1345 private void verifyActiveNetwork(int transport) {
1346 // Test getActiveNetworkInfo()
1347 assertNotNull(mCm.getActiveNetworkInfo());
1348 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1349 // Test getActiveNetwork()
1350 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001351 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001352 if (!NetworkCapabilities.isValidTransport(transport)) {
1353 throw new IllegalStateException("Unknown transport " + transport);
1354 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001355 switch (transport) {
1356 case TRANSPORT_WIFI:
1357 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1358 break;
1359 case TRANSPORT_CELLULAR:
1360 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1361 break;
1362 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001363 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001364 }
1365 // Test getNetworkInfo(Network)
1366 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001367 assertEquals(transportToLegacyType(transport),
1368 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001369 // Test getNetworkCapabilities(Network)
1370 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1371 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1372 }
1373
1374 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001375 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001376 // Test getActiveNetworkInfo()
1377 assertNull(mCm.getActiveNetworkInfo());
1378 // Test getActiveNetwork()
1379 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001380 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001381 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001382 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001383 }
1384
1385 /**
1386 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1387 * broadcasts are received.
1388 */
1389 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1390 final ConditionVariable cv = new ConditionVariable();
1391 mServiceContext.registerReceiver(new BroadcastReceiver() {
1392 private int remaining = count;
1393 public void onReceive(Context context, Intent intent) {
1394 if (--remaining == 0) {
1395 cv.open();
1396 mServiceContext.unregisterReceiver(this);
1397 }
1398 }
1399 }, new IntentFilter(CONNECTIVITY_ACTION));
1400 return cv;
1401 }
1402
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001403 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001404 public void testNetworkTypes() {
1405 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1406 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1407 // will fail. Failing here is much easier to debug.
1408 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1409 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001410 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1411 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1412
1413 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1414 // mocks, this assert exercises the ConnectivityService code path that ensures that
1415 // TYPE_ETHERNET is supported if the ethernet service is running.
1416 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001417 }
1418
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001419 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001420 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001421 verifyNoNetwork();
1422 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1423 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1424 assertNull(mCm.getActiveNetworkInfo());
1425 assertNull(mCm.getActiveNetwork());
1426 // Test bringing up validated cellular.
1427 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1428 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001429 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001430 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001431 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001432 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1433 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1434 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1435 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1436 // Test bringing up validated WiFi.
1437 cv = waitForConnectivityBroadcasts(2);
1438 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001439 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001440 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001441 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001442 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1443 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1444 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1445 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1446 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001447 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001448 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001449 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001450 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001451 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001452 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1453 // Test WiFi disconnect.
1454 cv = waitForConnectivityBroadcasts(1);
1455 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001456 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001457 verifyNoNetwork();
1458 }
1459
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001460 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001461 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1462 // Test bringing up unvalidated WiFi
1463 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1464 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1465 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001466 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001467 verifyActiveNetwork(TRANSPORT_WIFI);
1468 // Test bringing up unvalidated cellular
1469 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1470 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001471 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001472 verifyActiveNetwork(TRANSPORT_WIFI);
1473 // Test cellular disconnect.
1474 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001475 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001476 verifyActiveNetwork(TRANSPORT_WIFI);
1477 // Test bringing up validated cellular
1478 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1479 cv = waitForConnectivityBroadcasts(2);
1480 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001481 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001482 verifyActiveNetwork(TRANSPORT_CELLULAR);
1483 // Test cellular disconnect.
1484 cv = waitForConnectivityBroadcasts(2);
1485 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001486 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001487 verifyActiveNetwork(TRANSPORT_WIFI);
1488 // Test WiFi disconnect.
1489 cv = waitForConnectivityBroadcasts(1);
1490 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001491 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001492 verifyNoNetwork();
1493 }
1494
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001495 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001496 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1497 // Test bringing up unvalidated cellular.
1498 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1499 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1500 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001501 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001502 verifyActiveNetwork(TRANSPORT_CELLULAR);
1503 // Test bringing up unvalidated WiFi.
1504 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1505 cv = waitForConnectivityBroadcasts(2);
1506 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001507 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001508 verifyActiveNetwork(TRANSPORT_WIFI);
1509 // Test WiFi disconnect.
1510 cv = waitForConnectivityBroadcasts(2);
1511 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001512 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001513 verifyActiveNetwork(TRANSPORT_CELLULAR);
1514 // Test cellular disconnect.
1515 cv = waitForConnectivityBroadcasts(1);
1516 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001517 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001518 verifyNoNetwork();
1519 }
1520
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001521 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001522 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001523 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001524 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001525 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1526 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001527 waitFor(cv);
1528 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001529 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001530 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001531 // Test bringing up validated cellular.
1532 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001533 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001534 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001535 waitFor(cv);
1536 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001537 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1538 NET_CAPABILITY_VALIDATED));
1539 // Test cellular disconnect.
1540 cv = waitForConnectivityBroadcasts(2);
1541 mCellNetworkAgent.disconnect();
1542 waitFor(cv);
1543 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001544 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001545 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001546 NET_CAPABILITY_VALIDATED));
1547 }
1548
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001549 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001550 public void testCellularOutscoresWeakWifi() throws Exception {
1551 // Test bringing up validated cellular.
1552 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1553 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1554 mCellNetworkAgent.connect(true);
1555 waitFor(cv);
1556 verifyActiveNetwork(TRANSPORT_CELLULAR);
1557 // Test bringing up validated WiFi.
1558 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1559 cv = waitForConnectivityBroadcasts(2);
1560 mWiFiNetworkAgent.connect(true);
1561 waitFor(cv);
1562 verifyActiveNetwork(TRANSPORT_WIFI);
1563 // Test WiFi getting really weak.
1564 cv = waitForConnectivityBroadcasts(2);
1565 mWiFiNetworkAgent.adjustScore(-11);
1566 waitFor(cv);
1567 verifyActiveNetwork(TRANSPORT_CELLULAR);
1568 // Test WiFi restoring signal strength.
1569 cv = waitForConnectivityBroadcasts(2);
1570 mWiFiNetworkAgent.adjustScore(11);
1571 waitFor(cv);
1572 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001573 }
1574
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001575 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001576 public void testReapingNetwork() throws Exception {
1577 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1578 // Expect it to be torn down immediately because it satisfies no requests.
1579 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1580 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1581 mWiFiNetworkAgent.connectWithoutInternet();
1582 waitFor(cv);
1583 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1584 // Expect it to be torn down immediately because it satisfies no requests.
1585 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1586 cv = mCellNetworkAgent.getDisconnectedCV();
1587 mCellNetworkAgent.connectWithoutInternet();
1588 waitFor(cv);
1589 // Test bringing up validated WiFi.
1590 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1591 cv = waitForConnectivityBroadcasts(1);
1592 mWiFiNetworkAgent.connect(true);
1593 waitFor(cv);
1594 verifyActiveNetwork(TRANSPORT_WIFI);
1595 // Test bringing up unvalidated cellular.
1596 // Expect it to be torn down because it could never be the highest scoring network
1597 // satisfying the default request even if it validated.
1598 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1599 cv = mCellNetworkAgent.getDisconnectedCV();
1600 mCellNetworkAgent.connect(false);
1601 waitFor(cv);
1602 verifyActiveNetwork(TRANSPORT_WIFI);
1603 cv = mWiFiNetworkAgent.getDisconnectedCV();
1604 mWiFiNetworkAgent.disconnect();
1605 waitFor(cv);
1606 }
1607
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001608 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001609 public void testCellularFallback() throws Exception {
1610 // Test bringing up validated cellular.
1611 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1612 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1613 mCellNetworkAgent.connect(true);
1614 waitFor(cv);
1615 verifyActiveNetwork(TRANSPORT_CELLULAR);
1616 // Test bringing up validated WiFi.
1617 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1618 cv = waitForConnectivityBroadcasts(2);
1619 mWiFiNetworkAgent.connect(true);
1620 waitFor(cv);
1621 verifyActiveNetwork(TRANSPORT_WIFI);
1622 // Reevaluate WiFi (it'll instantly fail DNS).
1623 cv = waitForConnectivityBroadcasts(2);
1624 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1625 NET_CAPABILITY_VALIDATED));
1626 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1627 // Should quickly fall back to Cellular.
1628 waitFor(cv);
1629 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1630 NET_CAPABILITY_VALIDATED));
1631 verifyActiveNetwork(TRANSPORT_CELLULAR);
1632 // Reevaluate cellular (it'll instantly fail DNS).
1633 cv = waitForConnectivityBroadcasts(2);
1634 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1635 NET_CAPABILITY_VALIDATED));
1636 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1637 // Should quickly fall back to WiFi.
1638 waitFor(cv);
1639 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1640 NET_CAPABILITY_VALIDATED));
1641 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1642 NET_CAPABILITY_VALIDATED));
1643 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001644 }
1645
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001646 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001647 public void testWiFiFallback() throws Exception {
1648 // Test bringing up unvalidated WiFi.
1649 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1650 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1651 mWiFiNetworkAgent.connect(false);
1652 waitFor(cv);
1653 verifyActiveNetwork(TRANSPORT_WIFI);
1654 // Test bringing up validated cellular.
1655 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1656 cv = waitForConnectivityBroadcasts(2);
1657 mCellNetworkAgent.connect(true);
1658 waitFor(cv);
1659 verifyActiveNetwork(TRANSPORT_CELLULAR);
1660 // Reevaluate cellular (it'll instantly fail DNS).
1661 cv = waitForConnectivityBroadcasts(2);
1662 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1663 NET_CAPABILITY_VALIDATED));
1664 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1665 // Should quickly fall back to WiFi.
1666 waitFor(cv);
1667 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1668 NET_CAPABILITY_VALIDATED));
1669 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001670 }
1671
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001672 @Test
1673 public void testRequiresValidation() {
1674 assertTrue(NetworkMonitorUtils.isValidationRequired(
1675 mCm.getDefaultRequest().networkCapabilities));
1676 }
1677
Paul Jensen3d911462015-06-12 06:40:24 -04001678 enum CallbackState {
1679 NONE,
1680 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001681 NETWORK_CAPABILITIES,
1682 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001683 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001684 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001685 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001686 LOST,
Mike Yuf9729752018-08-17 15:22:05 +08001687 UNAVAILABLE,
1688 BLOCKED_STATUS
Paul Jensen3d911462015-06-12 06:40:24 -04001689 }
1690
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001691 private static class CallbackInfo {
1692 public final CallbackState state;
1693 public final Network network;
1694 public final Object arg;
1695 public CallbackInfo(CallbackState s, Network n, Object o) {
1696 state = s; network = n; arg = o;
1697 }
1698 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001699 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001700 }
1701 @Override
1702 public boolean equals(Object o) {
1703 if (!(o instanceof CallbackInfo)) return false;
1704 // Ignore timeMs, since it's unpredictable.
1705 CallbackInfo other = (CallbackInfo) o;
1706 return (state == other.state) && Objects.equals(network, other.network);
1707 }
1708 @Override
1709 public int hashCode() {
1710 return Objects.hash(state, network);
1711 }
1712 }
1713
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001714 /**
1715 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1716 * this class receives, by calling expectCallback() exactly once each time a callback is
1717 * received. assertNoCallback may be called at any time.
1718 */
Paul Jensen3d911462015-06-12 06:40:24 -04001719 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001720 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001721 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001722
Erik Klineacdd6392016-07-07 16:50:58 +09001723 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001724 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001725 }
Paul Jensen3d911462015-06-12 06:40:24 -04001726
Erik Klineacdd6392016-07-07 16:50:58 +09001727 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001728 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001729 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001730 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001731 }
1732
Erik Klineacdd6392016-07-07 16:50:58 +09001733 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001734 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1735 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1736 }
1737
1738 @Override
1739 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1740 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1741 }
1742
1743 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001744 public void onUnavailable() {
1745 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1746 }
1747
1748 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001749 public void onNetworkSuspended(Network network) {
1750 setLastCallback(CallbackState.SUSPENDED, network, null);
1751 }
1752
1753 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001754 public void onNetworkResumed(Network network) {
1755 setLastCallback(CallbackState.RESUMED, network, null);
1756 }
1757
1758 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001759 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001760 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001761 }
1762
Erik Klineacdd6392016-07-07 16:50:58 +09001763 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001764 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001765 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001766 setLastCallback(CallbackState.LOST, network, null);
1767 }
1768
Mike Yuf9729752018-08-17 15:22:05 +08001769 @Override
1770 public void onBlockedStatusChanged(Network network, boolean blocked) {
1771 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1772 }
1773
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001774 public Network getLastAvailableNetwork() {
1775 return mLastAvailableNetwork;
1776 }
1777
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001778 CallbackInfo nextCallback(int timeoutMs) {
1779 CallbackInfo cb = null;
1780 try {
1781 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1782 } catch (InterruptedException e) {
1783 }
1784 if (cb == null) {
1785 // LinkedBlockingQueue.poll() returns null if it timeouts.
1786 fail("Did not receive callback after " + timeoutMs + "ms");
1787 }
1788 return cb;
1789 }
1790
Erik Kline1d3db322017-02-28 16:20:20 +09001791 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1792 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1793 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001794 CallbackInfo actual = nextCallback(timeoutMs);
1795 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001796
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001797 if (state == CallbackState.LOSING) {
1798 String msg = String.format(
1799 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001800 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001801 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001802 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001803 }
Erik Kline1d3db322017-02-28 16:20:20 +09001804
1805 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001806 }
1807
Erik Kline1d3db322017-02-28 16:20:20 +09001808 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001809 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001810 }
1811
Hugo Benichi16f0a942017-06-20 14:07:59 +09001812 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001813 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09001814 }
1815
1816 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1817 int timeLeft = timeoutMs;
1818 while (timeLeft > 0) {
1819 long start = SystemClock.elapsedRealtime();
1820 CallbackInfo info = nextCallback(timeLeft);
1821 if (fn.test(info)) {
1822 return info;
1823 }
1824 timeLeft -= (SystemClock.elapsedRealtime() - start);
1825 }
1826 fail("Did not receive expected callback after " + timeoutMs + "ms");
1827 return null;
1828 }
1829
Lorenzo Colitti27334542018-01-12 16:22:21 +09001830 // Expects onAvailable and the callbacks that follow it. These are:
1831 // - onSuspended, iff the network was suspended when the callbacks fire.
1832 // - onCapabilitiesChanged.
1833 // - onLinkPropertiesChanged.
Mike Yuf9729752018-08-17 15:22:05 +08001834 // - onBlockedStatusChanged.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001835 //
1836 // @param agent the network to expect the callbacks on.
1837 // @param expectSuspended whether to expect a SUSPENDED callback.
1838 // @param expectValidated the expected value of the VALIDATED capability in the
1839 // onCapabilitiesChanged callback.
1840 // @param timeoutMs how long to wait for the callbacks.
1841 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
Mike Yuf9729752018-08-17 15:22:05 +08001842 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001843 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001844 if (expectSuspended) {
1845 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001846 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001847 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001848 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001849 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001850 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001851 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001852 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Mike Yuf9729752018-08-17 15:22:05 +08001853 expectBlockedStatusCallback(expectBlocked, agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001854 }
1855
Lorenzo Colitti27334542018-01-12 16:22:21 +09001856 // Expects the available callbacks (validated), plus onSuspended.
1857 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
Mike Yuf9729752018-08-17 15:22:05 +08001858 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001859 }
1860
Lorenzo Colitti27334542018-01-12 16:22:21 +09001861 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001862 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1863 }
1864
1865 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1866 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001867 }
1868
Lorenzo Colitti27334542018-01-12 16:22:21 +09001869 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001870 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1871 }
1872
1873 void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1874 expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001875 }
1876
1877 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1878 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1879 // one we just sent.
1880 // TODO: this is likely a bug. Fix it and remove this method.
1881 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001882 expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001883 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001884 expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
Mike Yuf9729752018-08-17 15:22:05 +08001885 // Implicitly check the network is allowed to use.
1886 // TODO: should we need to consider if network is in blocked status in this case?
1887 expectBlockedStatusCallback(false, agent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001888 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1889 assertEquals(nc1, nc2);
1890 }
1891
1892 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1893 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1894 // when a network connects and satisfies a callback, and then immediately validates.
1895 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1896 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001897 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1898 }
1899
Lorenzo Colitti27334542018-01-12 16:22:21 +09001900 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001901 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001902 }
1903
1904 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1905 int timeoutMs) {
1906 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001907 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1908 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001909 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001910 }
1911
Lorenzo Colitti27334542018-01-12 16:22:21 +09001912 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001913 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001914 }
1915
1916 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1917 int timeoutMs) {
1918 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001919 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1920 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001921 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001922 }
1923
Chalard Jean0b214af2018-01-12 17:22:49 +09001924 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1925 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001926 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1927 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001928 }
1929
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09001930 void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1931 CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1932 assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1933 fn.test((LinkProperties) cbi.arg));
1934 }
1935
Mike Yuf9729752018-08-17 15:22:05 +08001936 void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1937 CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1938 boolean actualBlocked = (boolean) cbi.arg;
1939 assertEquals(expectBlocked, actualBlocked);
1940 }
1941
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001942 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001943 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001944 CallbackInfo c = mCallbacks.peek();
1945 assertNull("Unexpected callback: " + c, c);
1946 }
1947 }
1948
1949 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1950 // only be declared in a static or top level type".
1951 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1952 for (TestNetworkCallback c : callbacks) {
1953 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001954 }
1955 }
1956
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001957 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001958 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001959 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001960 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1961 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001962 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1963 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001964 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1965 .addTransportType(TRANSPORT_WIFI).build();
1966 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1967 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001968 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001969 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1970 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1971
1972 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001973 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1974 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1975 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001976 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1977 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001978 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1979 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001980 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001981
Paul Jensen3d911462015-06-12 06:40:24 -04001982 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1983 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001984 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001985 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001986 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1987
Paul Jensen3d911462015-06-12 06:40:24 -04001988 cv = waitForConnectivityBroadcasts(2);
1989 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1990 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001991 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1992 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001993 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1994 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001995 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001996
Paul Jensen3d911462015-06-12 06:40:24 -04001997 cv = waitForConnectivityBroadcasts(2);
1998 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001999 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2000 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09002001 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04002002 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002003 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002004
Paul Jensen3d911462015-06-12 06:40:24 -04002005 cv = waitForConnectivityBroadcasts(1);
2006 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002007 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2008 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002009 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002010 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002011
2012 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04002013 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2014 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002015 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2016 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002017 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002018 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002019
Paul Jensen3d911462015-06-12 06:40:24 -04002020 // This should not trigger spurious onAvailable() callbacks, b/21762680.
2021 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09002022 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002023 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002024 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2025
Paul Jensen3d911462015-06-12 06:40:24 -04002026 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2027 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002028 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002029 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002030 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002031 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002032 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002033 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002034 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002035
Paul Jensen3d911462015-06-12 06:40:24 -04002036 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002037 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2038 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2039 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002040
Paul Jensen3d911462015-06-12 06:40:24 -04002041 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002042 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2043 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2044 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002045 }
2046
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002047 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002048 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002049 // This test would be flaky with the default 120ms timer: that is short enough that
2050 // lingered networks are torn down before assertions can be run. We don't want to mock the
2051 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
2052 // in detecting races.
2053 mService.mLingerDelayMs = 300;
2054
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002055 NetworkRequest request = new NetworkRequest.Builder()
2056 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
2057 .build();
2058 TestNetworkCallback callback = new TestNetworkCallback();
2059 mCm.registerNetworkCallback(request, callback);
2060
2061 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2062 mCm.registerDefaultNetworkCallback(defaultCallback);
2063
2064 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2065 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2066 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2067
2068 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2069 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2070 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2071
2072 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002073 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2074 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002075 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002076 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002077
2078 mWiFiNetworkAgent.connect(true);
2079 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
2080 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002081 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002082 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002083 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002084 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002085 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002086 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002087 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002088
2089 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002090 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002091 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002092 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002093 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002094 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002095 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002096 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002097
2098 mEthernetNetworkAgent.disconnect();
2099 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2100 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002101 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002102 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002103
2104 for (int i = 0; i < 4; i++) {
2105 MockNetworkAgent oldNetwork, newNetwork;
2106 if (i % 2 == 0) {
2107 mWiFiNetworkAgent.adjustScore(-15);
2108 oldNetwork = mWiFiNetworkAgent;
2109 newNetwork = mCellNetworkAgent;
2110 } else {
2111 mWiFiNetworkAgent.adjustScore(15);
2112 oldNetwork = mCellNetworkAgent;
2113 newNetwork = mWiFiNetworkAgent;
2114
2115 }
2116 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002117 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2118 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002119 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002120 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2121 }
2122 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2123
2124 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2125 // if the network is still up.
2126 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002127 // We expect a notification about the capabilities change, and nothing else.
2128 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2129 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002130 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002131 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002132
2133 // Wifi no longer satisfies our listen, which is for an unmetered network.
2134 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002135 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2136
2137 // Disconnect our test networks.
2138 mWiFiNetworkAgent.disconnect();
2139 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002140 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002141 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002142 mCellNetworkAgent.disconnect();
2143 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002144 waitForIdle();
2145 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002146
2147 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002148 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002149
2150 // Check that a network is only lingered or torn down if it would not satisfy a request even
2151 // if it validated.
2152 request = new NetworkRequest.Builder().clearCapabilities().build();
2153 callback = new TestNetworkCallback();
2154
2155 mCm.registerNetworkCallback(request, callback);
2156
2157 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2158 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002159 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2160 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002161 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002162 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002163
2164 // Bring up wifi with a score of 20.
2165 // Cell stays up because it would satisfy the default request if it validated.
2166 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2167 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002168 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2169 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002170 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002171 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002172
2173 mWiFiNetworkAgent.disconnect();
2174 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2175 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002176 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002177 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002178 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002179
2180 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002181 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002182 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2183 mWiFiNetworkAgent.adjustScore(50);
2184 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002185 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002186 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002187 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002188 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002189 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002190
2191 // Tear down wifi.
2192 mWiFiNetworkAgent.disconnect();
2193 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2194 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002195 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002196 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002197 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002198
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002199 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2200 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002201 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2202 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002203 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002204 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002205 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002206 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002207 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002208 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002209 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002210
2211 mWiFiNetworkAgent.disconnect();
2212 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002213 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002214 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002215 mCellNetworkAgent.disconnect();
2216 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2217 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002218 waitForIdle();
2219 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002220
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002221 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002222 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2223 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002224 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2225 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002226 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002227 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2228 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002229 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2230 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002231 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002232 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002233 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002234 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002235
2236 NetworkRequest cellRequest = new NetworkRequest.Builder()
2237 .addTransportType(TRANSPORT_CELLULAR).build();
2238 NetworkCallback noopCallback = new NetworkCallback();
2239 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002240 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2241 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002242 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002243 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002244
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002245 // Similar to the above: lingering can start even after the lingered request is removed.
2246 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002247 mWiFiNetworkAgent.disconnect();
2248 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002249 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002250 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002251 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002252
2253 // Cell is now the default network. Pin it with a cell-specific request.
2254 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2255 mCm.requestNetwork(cellRequest, noopCallback);
2256
2257 // Now connect wifi, and expect it to become the default network.
2258 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2259 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002260 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2261 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002262 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002263 // The default request is lingering on cell, but nothing happens to cell, and we send no
2264 // callbacks for it, because it's kept up by cellRequest.
2265 callback.assertNoCallback();
2266 // Now unregister cellRequest and expect cell to start lingering.
2267 mCm.unregisterNetworkCallback(noopCallback);
2268 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2269
2270 // Let linger run its course.
2271 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002272 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002273 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002274
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002275 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2276 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2277 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002278 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002279 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2280 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002281 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002282 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2283 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002284 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2285 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002286 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002287
2288 // Let linger run its course.
2289 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2290
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002291 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002292 mEthernetNetworkAgent.disconnect();
2293 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2294 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2295 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002296
2297 mCm.unregisterNetworkCallback(callback);
2298 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002299 mCm.unregisterNetworkCallback(trackDefaultCallback);
2300 }
2301
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002302 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002303 public void testNetworkGoesIntoBackgroundAfterLinger() {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002304 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002305 NetworkRequest request = new NetworkRequest.Builder()
2306 .clearCapabilities()
2307 .build();
2308 TestNetworkCallback callback = new TestNetworkCallback();
2309 mCm.registerNetworkCallback(request, callback);
2310
2311 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2312 mCm.registerDefaultNetworkCallback(defaultCallback);
2313
2314 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2315 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2316
2317 mCellNetworkAgent.connect(true);
2318 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2319 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2320
2321 // Wifi comes up and cell lingers.
2322 mWiFiNetworkAgent.connect(true);
2323 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2324 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2325 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2326 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2327
2328 // File a request for cellular, then release it.
2329 NetworkRequest cellRequest = new NetworkRequest.Builder()
2330 .addTransportType(TRANSPORT_CELLULAR).build();
2331 NetworkCallback noopCallback = new NetworkCallback();
2332 mCm.requestNetwork(cellRequest, noopCallback);
2333 mCm.unregisterNetworkCallback(noopCallback);
2334 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2335
2336 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002337 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002338 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2339 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2340 lingerTimeoutMs);
2341
2342 // Clean up.
2343 mCm.unregisterNetworkCallback(defaultCallback);
2344 mCm.unregisterNetworkCallback(callback);
2345 }
2346
2347 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002348 public void testExplicitlySelected() {
2349 NetworkRequest request = new NetworkRequest.Builder()
2350 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2351 .build();
2352 TestNetworkCallback callback = new TestNetworkCallback();
2353 mCm.registerNetworkCallback(request, callback);
2354
2355 // Bring up validated cell.
2356 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2357 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002358 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002359
2360 // Bring up unvalidated wifi with explicitlySelected=true.
2361 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2362 mWiFiNetworkAgent.explicitlySelected(false);
2363 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002364 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002365
2366 // Cell Remains the default.
2367 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2368
2369 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2370 // it's explicitly selected.
2371 mWiFiNetworkAgent.adjustScore(-40);
2372 mWiFiNetworkAgent.adjustScore(40);
2373 callback.assertNoCallback();
2374
2375 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2376 // wifi even though it's unvalidated.
2377 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2378 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2379 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2380
2381 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2382 mWiFiNetworkAgent.disconnect();
2383 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2384 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2385 mWiFiNetworkAgent.explicitlySelected(false);
2386 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002387 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002388
2389 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2390 // network to disconnect.
2391 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2392 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2393
2394 // Reconnect, again with explicitlySelected=true, but this time validate.
2395 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2396 mWiFiNetworkAgent.explicitlySelected(false);
2397 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002398 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002399 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2400 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2401 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2402
2403 // BUG: the network will no longer linger, even though it's validated and outscored.
2404 // TODO: fix this.
2405 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2406 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002407 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002408 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2409 callback.assertNoCallback();
2410
2411 // Clean up.
2412 mWiFiNetworkAgent.disconnect();
2413 mCellNetworkAgent.disconnect();
2414 mEthernetNetworkAgent.disconnect();
2415
2416 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2417 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2418 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002419 }
2420
Chalard Jean05ab6812018-05-02 21:14:54 +09002421 private int[] makeIntArray(final int size, final int value) {
2422 final int[] array = new int[size];
2423 Arrays.fill(array, value);
2424 return array;
2425 }
2426
Paul Jensen85cf78e2015-06-25 13:25:07 -04002427 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002428 // Verify NOT_RESTRICTED is set appropriately
2429 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2430 .build().networkCapabilities;
2431 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2432 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2433 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002434 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002435 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2436 } else {
2437 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2438 }
2439
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002440 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002441 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002442 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2443 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002444 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002445 mServiceContext, "testFactory", filter);
2446 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002447 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002448 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002449 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002450 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002451 int expectedRequestCount = 1;
2452 NetworkCallback networkCallback = null;
2453 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2454 // add one.
2455 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002456 assertFalse(testFactory.getMyStartRequested());
2457 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2458 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002459 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002460 mCm.requestNetwork(request, networkCallback);
2461 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002462 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002463 }
Paul Jensen3d911462015-06-12 06:40:24 -04002464 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002465 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2466 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002467
Paul Jensen85cf78e2015-06-25 13:25:07 -04002468 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002469 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002470 // Rather than create a validated network which complicates things by registering it's
2471 // own NetworkRequest during startup, just bump up the score to cancel out the
2472 // unvalidated penalty.
2473 testAgent.adjustScore(40);
2474 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002475
2476 // When testAgent connects, ConnectivityService will re-send us all current requests with
2477 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2478 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002479 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002480 testAgent.connect(false);
2481 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002482 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002483 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002484 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002485
Paul Jensen85cf78e2015-06-25 13:25:07 -04002486 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002487 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002488 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002489 ConnectivityManager.NetworkCallback[] networkCallbacks =
2490 new ConnectivityManager.NetworkCallback[10];
2491 for (int i = 0; i< networkCallbacks.length; i++) {
2492 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2493 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002494 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002495 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2496 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002497 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2498 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002499
Paul Jensen85cf78e2015-06-25 13:25:07 -04002500 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002501 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002502 for (int i = 0; i < networkCallbacks.length; i++) {
2503 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2504 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002505 testFactory.waitForNetworkRequests(expectedRequestCount);
2506 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002507
Paul Jensen85cf78e2015-06-25 13:25:07 -04002508 // Drop the higher scored network.
2509 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002510 // With the default network disconnecting, the requests are sent with score 0 to factories.
2511 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002512 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002513 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002514 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002515 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2516 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002517
2518 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002519 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002520 handlerThread.quit();
2521 }
2522
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002523 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002524 public void testNetworkFactoryRequests() throws Exception {
2525 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2526 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2527 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2528 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2529 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2530 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2531 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2532 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2533 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2534 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2535 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2536 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2537 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2538 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2539 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2540 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2541 }
2542
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002543 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002544 public void testNoMutableNetworkRequests() throws Exception {
2545 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002546 NetworkRequest request1 = new NetworkRequest.Builder()
2547 .addCapability(NET_CAPABILITY_VALIDATED)
2548 .build();
2549 NetworkRequest request2 = new NetworkRequest.Builder()
2550 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2551 .build();
2552
2553 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2554 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2555 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2556 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2557 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002558 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002559
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002560 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002561 public void testMMSonWiFi() throws Exception {
2562 // Test bringing up cellular without MMS NetworkRequest gets reaped
2563 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2564 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2565 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2566 mCellNetworkAgent.connectWithoutInternet();
2567 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002568 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002569 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002570 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002571
Paul Jensene0988542015-06-25 15:30:08 -04002572 // Test bringing up validated WiFi.
2573 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2574 cv = waitForConnectivityBroadcasts(1);
2575 mWiFiNetworkAgent.connect(true);
2576 waitFor(cv);
2577 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002578
Paul Jensene0988542015-06-25 15:30:08 -04002579 // Register MMS NetworkRequest
2580 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2581 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2582 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2583 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002584
Paul Jensene0988542015-06-25 15:30:08 -04002585 // Test bringing up unvalidated cellular with MMS
2586 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2587 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002588 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002589 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002590 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002591
Paul Jensene0988542015-06-25 15:30:08 -04002592 // Test releasing NetworkRequest disconnects cellular with MMS
2593 cv = mCellNetworkAgent.getDisconnectedCV();
2594 mCm.unregisterNetworkCallback(networkCallback);
2595 waitFor(cv);
2596 verifyActiveNetwork(TRANSPORT_WIFI);
2597 }
2598
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002599 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002600 public void testMMSonCell() throws Exception {
2601 // Test bringing up cellular without MMS
2602 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2603 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2604 mCellNetworkAgent.connect(false);
2605 waitFor(cv);
2606 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002607
Paul Jensene0988542015-06-25 15:30:08 -04002608 // Register MMS NetworkRequest
2609 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2610 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2611 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2612 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002613
Paul Jensene0988542015-06-25 15:30:08 -04002614 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002615 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2616 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2617 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002618 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002619 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002620
Paul Jensene0988542015-06-25 15:30:08 -04002621 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2622 cv = mmsNetworkAgent.getDisconnectedCV();
2623 mCm.unregisterNetworkCallback(networkCallback);
2624 waitFor(cv);
2625 verifyActiveNetwork(TRANSPORT_CELLULAR);
2626 }
2627
lucaslinf3b59b32019-03-26 17:49:49 +08002628 @Test
lucasline252a742019-03-12 13:08:03 +08002629 public void testPartialConnectivity() {
2630 // Register network callback.
2631 NetworkRequest request = new NetworkRequest.Builder()
2632 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2633 .build();
2634 TestNetworkCallback callback = new TestNetworkCallback();
2635 mCm.registerNetworkCallback(request, callback);
2636
2637 // Bring up validated mobile data.
2638 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2639 mCellNetworkAgent.connect(true);
2640 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2641
2642 // Bring up wifi with partial connectivity.
2643 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2644 mWiFiNetworkAgent.connectWithPartialConnectivity();
2645 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2646 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2647
2648 // Mobile data should be the default network.
2649 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2650 callback.assertNoCallback();
2651
lucaslinf3b59b32019-03-26 17:49:49 +08002652 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2653 // probe.
2654 mWiFiNetworkAgent.setNetworkValid();
lucasline252a742019-03-12 13:08:03 +08002655 // If the user chooses yes to use this partial connectivity wifi, switch the default
2656 // network to wifi and check if wifi becomes valid or not.
2657 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2658 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002659 // If user accepts partial connectivity network,
2660 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002661 waitForIdle();
2662 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002663 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002664 } catch (RemoteException e) {
2665 fail(e.getMessage());
2666 }
lucaslinf3b59b32019-03-26 17:49:49 +08002667 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2668 // validated.
2669 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
lucasline252a742019-03-12 13:08:03 +08002670 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2671 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2672 mWiFiNetworkAgent);
2673 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2674 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2675
2676 // Disconnect and reconnect wifi with partial connectivity again.
2677 mWiFiNetworkAgent.disconnect();
2678 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2679 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2680 mWiFiNetworkAgent.connectWithPartialConnectivity();
2681 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2682 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2683
2684 // Mobile data should be the default network.
2685 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2686
2687 // If the user chooses no, disconnect wifi immediately.
2688 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2689 false /* always */);
2690 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2691
2692 // If user accepted partial connectivity before, and device reconnects to that network
2693 // again, but now the network has full connectivity. The network shouldn't contain
2694 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2695 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2696 // acceptUnvalidated is also used as setting for accepting partial networks.
2697 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
2698 mWiFiNetworkAgent.connect(true);
lucaslinf3b59b32019-03-26 17:49:49 +08002699 // If user accepted partial connectivity network before,
2700 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2701 // ConnectivityService#updateNetworkInfo().
2702 waitForIdle();
2703 try {
2704 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2705 } catch (RemoteException e) {
2706 fail(e.getMessage());
2707 }
lucasline252a742019-03-12 13:08:03 +08002708 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2709 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2710 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2711 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2712 // Wifi should be the default network.
2713 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2714 mWiFiNetworkAgent.disconnect();
2715 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2716
2717 // If user accepted partial connectivity before, and now the device reconnects to the
2718 // partial connectivity network. The network should be valid and contain
2719 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2720 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2721 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
lucaslinf3b59b32019-03-26 17:49:49 +08002722 // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
2723 // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
2724 // to ConnectivityService first then send VALID. Once NetworkMonitor support
2725 // multi-testResult, this test case also need to be changed to meet the new design.
lucasline252a742019-03-12 13:08:03 +08002726 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002727 // If user accepted partial connectivity network before,
2728 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2729 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002730 waitForIdle();
2731 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002732 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002733 } catch (RemoteException e) {
2734 fail(e.getMessage());
2735 }
lucaslinf3b59b32019-03-26 17:49:49 +08002736 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002737 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
lucaslinf3b59b32019-03-26 17:49:49 +08002738 // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
2739 // NetworkMonitor detects partial connectivity
lucasline252a742019-03-12 13:08:03 +08002740 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002741 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2742 mWiFiNetworkAgent.setNetworkValid();
2743 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2744 // validated.
2745 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2746 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2747 mWiFiNetworkAgent.disconnect();
2748 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002749 }
2750
2751 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002752 public void testCaptivePortal() {
2753 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2754 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2755 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2756 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2757
2758 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2759 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2760 .addCapability(NET_CAPABILITY_VALIDATED).build();
2761 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002762
2763 // Bring up a network with a captive portal.
2764 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002765 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002766 String firstRedirectUrl = "http://example.com/firstPath";
2767 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002768 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002769 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002770
2771 // Take down network.
2772 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002773 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002774 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002775
2776 // Bring up a network with a captive portal.
2777 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002778 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002779 String secondRedirectUrl = "http://example.com/secondPath";
2780 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002781 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002782 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002783
2784 // Make captive portal disappear then revalidate.
2785 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002786 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002787 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002788 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002789
2790 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002791 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002792
2793 // Break network connectivity.
2794 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002795 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002796 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002797 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002798 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002799
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002800 @Test
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002801 public void testCaptivePortalApp() throws RemoteException {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002802 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2803 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2804 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2805 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2806
2807 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2808 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2809 .addCapability(NET_CAPABILITY_VALIDATED).build();
2810 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2811
2812 // Bring up wifi.
2813 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2814 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002815 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002816 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2817
2818 // Check that calling startCaptivePortalApp does nothing.
2819 final int fastTimeoutMs = 100;
2820 mCm.startCaptivePortalApp(wifiNetwork);
2821 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2822
2823 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002824 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002825 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002826 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002827 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2828
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002829 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002830 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002831 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2832 .launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002833
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002834 // Report that the captive portal is dismissed, and check that callbacks are fired
2835 mWiFiNetworkAgent.setNetworkValid();
2836 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002837 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002838 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2839
2840 mCm.unregisterNetworkCallback(validatedCallback);
2841 mCm.unregisterNetworkCallback(captivePortalCallback);
2842 }
2843
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002844 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002845 public void testAvoidOrIgnoreCaptivePortals() {
2846 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2847 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2848 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2849 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2850
2851 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2852 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2853 .addCapability(NET_CAPABILITY_VALIDATED).build();
2854 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2855
2856 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2857 // Bring up a network with a captive portal.
2858 // Expect it to fail to connect and not result in any callbacks.
2859 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2860 String firstRedirectUrl = "http://example.com/firstPath";
2861
2862 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2863 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2864 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2865 waitFor(disconnectCv);
2866 waitFor(avoidCv);
2867
2868 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002869 }
2870
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002871 private NetworkRequest.Builder newWifiRequestBuilder() {
2872 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2873 }
2874
Etan Cohen836ad572018-12-30 17:59:59 -08002875 /**
2876 * Verify request matching behavior with network specifiers.
2877 *
2878 * Note: this test is somewhat problematic since it involves removing capabilities from
2879 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2880 * as a WTF bug in
2881 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2882 * does work.
2883 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002884 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002885 public void testNetworkSpecifier() {
Etan Cohen836ad572018-12-30 17:59:59 -08002886 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2887 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2888 Parcelable {
2889 @Override
2890 public boolean satisfiedBy(NetworkSpecifier other) {
2891 return true;
2892 }
2893
2894 @Override
2895 public int describeContents() {
2896 return 0;
2897 }
2898
2899 @Override
2900 public void writeToParcel(Parcel dest, int flags) {}
2901
2902 @Override
2903 public NetworkSpecifier redact() {
2904 return null;
2905 }
2906 }
2907
2908 // A network specifier that matches either another LocalNetworkSpecifier with the same
2909 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2910 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2911 private String mString;
2912
2913 LocalStringNetworkSpecifier(String string) {
2914 mString = string;
2915 }
2916
2917 @Override
2918 public boolean satisfiedBy(NetworkSpecifier other) {
2919 if (other instanceof LocalStringNetworkSpecifier) {
2920 return TextUtils.equals(mString,
2921 ((LocalStringNetworkSpecifier) other).mString);
2922 }
2923 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2924 return false;
2925 }
2926
2927 @Override
2928 public int describeContents() {
2929 return 0;
2930 }
2931 @Override
2932 public void writeToParcel(Parcel dest, int flags) {}
2933 }
2934
2935
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002936 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002937 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002938 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002939 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2940 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002941 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2942 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002943 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002944 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002945
2946 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2947 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2948 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002949 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002950 TestNetworkCallback cFoo = new TestNetworkCallback();
2951 TestNetworkCallback cBar = new TestNetworkCallback();
2952 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002953 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002954
2955 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2956 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2957 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002958 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002959 mCm.registerNetworkCallback(rFoo, cFoo);
2960 mCm.registerNetworkCallback(rBar, cBar);
2961
Etan Cohen836ad572018-12-30 17:59:59 -08002962 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2963 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2964
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002965 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2966 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002967 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2968 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2969 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2970 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002971 assertNoCallbacks(cFoo, cBar);
2972
Etan Cohen836ad572018-12-30 17:59:59 -08002973 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002974 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002975 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002976 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2977 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002978 }
Etan Cohen836ad572018-12-30 17:59:59 -08002979 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2980 mWiFiNetworkAgent);
2981 assertEquals(nsFoo,
2982 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002983 cFoo.assertNoCallback();
2984
Etan Cohen836ad572018-12-30 17:59:59 -08002985 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002986 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002987 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002988 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002989 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2990 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002991 }
Etan Cohen836ad572018-12-30 17:59:59 -08002992 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2993 mWiFiNetworkAgent);
2994 assertEquals(nsBar,
2995 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2996 cBar.assertNoCallback();
2997
2998 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2999 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3000 for (TestNetworkCallback c : emptyCallbacks) {
3001 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3002 mWiFiNetworkAgent);
3003 }
3004 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3005 mWiFiNetworkAgent);
3006 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3007 mWiFiNetworkAgent);
3008 assertNull(
3009 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3010 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003011 cBar.assertNoCallback();
3012
3013 mWiFiNetworkAgent.setNetworkSpecifier(null);
Etan Cohen836ad572018-12-30 17:59:59 -08003014 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003015 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3016 for (TestNetworkCallback c: emptyCallbacks) {
3017 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
3018 }
3019
Etan Cohen836ad572018-12-30 17:59:59 -08003020 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003021 }
3022
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003023 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08003024 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003025 try {
3026 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07003027 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
3028 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
3029 } catch (IllegalArgumentException expected) {
3030 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08003031 }
3032
Etan Cohenddb9ef02015-11-18 10:56:15 -08003033 try {
3034 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3035 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07003036 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08003037 mService.requestNetwork(networkCapabilities, null, 0, null,
3038 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07003039 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
3040 } catch (IllegalArgumentException expected) {
3041 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08003042 }
3043
Etan Cohena7434272017-04-03 12:17:51 -07003044 class NonParcelableSpecifier extends NetworkSpecifier {
3045 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
3046 };
3047 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3048 @Override public int describeContents() { return 0; }
3049 @Override public void writeToParcel(Parcel p, int flags) {}
3050 }
3051 NetworkRequest.Builder builder;
3052
3053 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3054 try {
3055 builder.setNetworkSpecifier(new NonParcelableSpecifier());
3056 Parcel parcelW = Parcel.obtain();
3057 builder.build().writeToParcel(parcelW, 0);
3058 fail("Parceling a non-parcelable specifier did not throw an exception");
3059 } catch (Exception e) {
3060 // expected
3061 }
3062
3063 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3064 builder.setNetworkSpecifier(new ParcelableSpecifier());
3065 NetworkRequest nr = builder.build();
3066 assertNotNull(nr);
3067
3068 try {
3069 Parcel parcelW = Parcel.obtain();
3070 nr.writeToParcel(parcelW, 0);
3071 byte[] bytes = parcelW.marshall();
3072 parcelW.recycle();
3073
3074 Parcel parcelR = Parcel.obtain();
3075 parcelR.unmarshall(bytes, 0, bytes.length);
3076 parcelR.setDataPosition(0);
3077 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
3078 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
3079 } catch (Exception e) {
3080 // expected
3081 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08003082 }
3083
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003084 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07003085 public void testNetworkSpecifierUidSpoofSecurityException() {
3086 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3087 @Override
3088 public boolean satisfiedBy(NetworkSpecifier other) {
3089 return true;
3090 }
3091
3092 @Override
3093 public void assertValidFromUid(int requestorUid) {
3094 throw new SecurityException("failure");
3095 }
3096
3097 @Override
3098 public int describeContents() { return 0; }
3099 @Override
3100 public void writeToParcel(Parcel dest, int flags) {}
3101 }
3102
3103 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3104 mWiFiNetworkAgent.connect(false);
3105
3106 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
3107 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
3108 networkSpecifier).build();
3109 TestNetworkCallback networkCallback = new TestNetworkCallback();
3110 try {
3111 mCm.requestNetwork(networkRequest, networkCallback);
3112 fail("Network request with spoofed UID did not throw a SecurityException");
3113 } catch (SecurityException e) {
3114 // expected
3115 }
3116 }
3117
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003118 @Test
paulhu3d67f532019-03-22 16:35:06 +08003119 public void testInvalidSignalStrength() {
3120 NetworkRequest r = new NetworkRequest.Builder()
3121 .addCapability(NET_CAPABILITY_INTERNET)
3122 .addTransportType(TRANSPORT_WIFI)
3123 .setSignalStrength(-75)
3124 .build();
3125 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3126 // permission should get SecurityException.
3127 try {
3128 mCm.registerNetworkCallback(r, new NetworkCallback());
3129 fail("Expected SecurityException filing a callback with signal strength");
3130 } catch (SecurityException expected) {
3131 // expected
3132 }
3133
3134 try {
3135 mCm.registerNetworkCallback(r, PendingIntent.getService(
3136 mServiceContext, 0, new Intent(), 0));
3137 fail("Expected SecurityException filing a callback with signal strength");
3138 } catch (SecurityException expected) {
3139 // expected
3140 }
3141
3142 // Requesting a Network with signal strength should get IllegalArgumentException.
3143 try {
3144 mCm.requestNetwork(r, new NetworkCallback());
3145 fail("Expected IllegalArgumentException filing a request with signal strength");
3146 } catch (IllegalArgumentException expected) {
3147 // expected
3148 }
3149
3150 try {
3151 mCm.requestNetwork(r, PendingIntent.getService(
3152 mServiceContext, 0, new Intent(), 0));
3153 fail("Expected IllegalArgumentException filing a request with signal strength");
3154 } catch (IllegalArgumentException expected) {
3155 // expected
3156 }
3157 }
3158
3159 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003160 public void testRegisterDefaultNetworkCallback() throws Exception {
3161 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3162 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3163 defaultNetworkCallback.assertNoCallback();
3164
3165 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3166 // whenever Wi-Fi is up. Without this, the mobile network agent is
3167 // reaped before any other activity can take place.
3168 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3169 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3170 .addTransportType(TRANSPORT_CELLULAR).build();
3171 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3172 cellNetworkCallback.assertNoCallback();
3173
3174 // Bring up cell and expect CALLBACK_AVAILABLE.
3175 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3176 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003177 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3178 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003179 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003180
3181 // Bring up wifi and expect CALLBACK_AVAILABLE.
3182 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3183 mWiFiNetworkAgent.connect(true);
3184 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003185 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003186 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003187
3188 // Bring down cell. Expect no default network callback, since it wasn't the default.
3189 mCellNetworkAgent.disconnect();
3190 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3191 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003192 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003193
3194 // Bring up cell. Expect no default network callback, since it won't be the default.
3195 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3196 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003197 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003198 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003199 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003200
3201 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3202 // followed by AVAILABLE cell.
3203 mWiFiNetworkAgent.disconnect();
3204 cellNetworkCallback.assertNoCallback();
3205 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003206 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003207 mCellNetworkAgent.disconnect();
3208 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3209 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003210 waitForIdle();
3211 assertEquals(null, mCm.getActiveNetwork());
3212
3213 final int uid = Process.myUid();
3214 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
3215 final ArraySet<UidRange> ranges = new ArraySet<>();
3216 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003217 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3218 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003219 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003220 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003221 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3222 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3223
3224 vpnNetworkAgent.disconnect();
3225 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3226 waitForIdle();
3227 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003228 }
3229
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003230 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003231 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003232 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003233 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003234 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3235 .addTransportType(TRANSPORT_CELLULAR).build();
3236 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3237
3238 // Bring up the mobile network.
3239 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3240 mCellNetworkAgent.connect(true);
3241
Erik Kline1d3db322017-02-28 16:20:20 +09003242 // We should get onAvailable(), onCapabilitiesChanged(), and
3243 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3244 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003245 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003246 cellNetworkCallback.assertNoCallback();
3247
3248 // Update LinkProperties.
3249 final LinkProperties lp = new LinkProperties();
3250 lp.setInterfaceName("foonet_data0");
3251 mCellNetworkAgent.sendLinkProperties(lp);
3252 // We should get onLinkPropertiesChanged().
3253 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
3254 cellNetworkCallback.assertNoCallback();
3255
Erik Kline1d3db322017-02-28 16:20:20 +09003256 // Suspend the network.
3257 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003258 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3259 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003260 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
3261 cellNetworkCallback.assertNoCallback();
3262
Erik Klineacdd6392016-07-07 16:50:58 +09003263 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003264 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003265 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003266 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3267 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003268 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003269 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003270 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3271
3272 mCellNetworkAgent.resume();
3273 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3274 mCellNetworkAgent);
3275 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
3276 cellNetworkCallback.assertNoCallback();
3277
3278 dfltNetworkCallback = new TestNetworkCallback();
3279 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3280 // This time onNetworkSuspended should not be called.
3281 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3282 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003283
Erik Klineacdd6392016-07-07 16:50:58 +09003284 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3285 mCm.unregisterNetworkCallback(cellNetworkCallback);
3286 }
3287
Calvin On1f64f3f2016-10-11 15:10:46 -07003288 private void setCaptivePortalMode(int mode) {
3289 ContentResolver cr = mServiceContext.getContentResolver();
3290 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3291 }
3292
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003293 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003294 ContentResolver cr = mServiceContext.getContentResolver();
3295 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003296 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003297 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003298 }
3299
Erik Kline79c6d052018-03-21 07:18:33 -07003300 private void setPrivateDnsSettings(String mode, String specifier) {
3301 final ContentResolver cr = mServiceContext.getContentResolver();
3302 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3303 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3304 mService.updatePrivateDnsSettings();
3305 waitForIdle();
3306 }
3307
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003308 private boolean isForegroundNetwork(MockNetworkAgent network) {
3309 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3310 assertNotNull(nc);
3311 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3312 }
3313
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003314 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003315 public void testBackgroundNetworks() throws Exception {
3316 // Create a background request. We can't do this ourselves because ConnectivityService
3317 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003318 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003319 final NetworkRequest request = new NetworkRequest.Builder().build();
3320 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3321 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3322 final TestNetworkCallback callback = new TestNetworkCallback();
3323 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3324 mCm.registerNetworkCallback(request, callback);
3325 mCm.registerNetworkCallback(fgRequest, fgCallback);
3326
3327 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3328 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003329 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3330 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003331 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3332
3333 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3334 mWiFiNetworkAgent.connect(true);
3335
3336 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003337 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003338 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003339 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003340 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003341 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003342 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003343 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3344 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3345
3346 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003347 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003348 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3349 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003350 // Expect a network capabilities update sans FOREGROUND.
3351 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003352 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3353 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3354
3355 // File a cell request and check that cell comes into the foreground.
3356 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3357 .addTransportType(TRANSPORT_CELLULAR).build();
3358 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3359 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003360 // NOTE: This request causes the network's capabilities to change. This
3361 // is currently delivered before the onAvailable() callbacks.
3362 // TODO: Fix this.
3363 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003364 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3365 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003366 // Expect a network capabilities update with FOREGROUND, because the most recent
3367 // request causes its state to change.
3368 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003369 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3370 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3371
3372 // Release the request. The network immediately goes into the background, since it was not
3373 // lingering.
3374 mCm.unregisterNetworkCallback(cellCallback);
3375 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003376 // Expect a network capabilities update sans FOREGROUND.
3377 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003378 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3379 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3380
3381 // Disconnect wifi and check that cell is foreground again.
3382 mWiFiNetworkAgent.disconnect();
3383 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3384 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003385 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003386 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3387
3388 mCm.unregisterNetworkCallback(callback);
3389 mCm.unregisterNetworkCallback(fgCallback);
3390 }
3391
Hugo Benichi849b81b2017-05-25 13:42:31 +09003392 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003393 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003394 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003395 // Benchmarks connecting and switching performance in the presence of a large number of
3396 // NetworkRequests.
3397 // 1. File NUM_REQUESTS requests.
3398 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3399 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3400 // and NUM_REQUESTS onAvailable callbacks to fire.
3401 // See how long it took.
3402 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003403 final int REGISTER_TIME_LIMIT_MS = 200;
3404 final int CONNECT_TIME_LIMIT_MS = 60;
3405 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003406 final int UNREGISTER_TIME_LIMIT_MS = 20;
3407
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003408 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3409 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3410 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3411 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3412
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003413 for (int i = 0; i < NUM_REQUESTS; i++) {
3414 callbacks[i] = new NetworkCallback() {
3415 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3416 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3417 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003418 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003419
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003420 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3421 for (NetworkCallback cb : callbacks) {
3422 mCm.registerNetworkCallback(request, cb);
3423 }
3424 });
3425
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003426 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3427 // Don't request that the network validate, because otherwise connect() will block until
3428 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3429 // and we won't actually measure anything.
3430 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003431
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003432 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003433 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003434 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003435 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3436 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3437 onAvailableDispatchingDuration));
3438 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3439 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3440 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003441
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003442 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003443 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003444 mWiFiNetworkAgent.adjustScore(40);
3445 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003446
3447 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003448 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003449 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003450 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3451 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3452 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3453 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3454 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003455
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003456 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3457 for (NetworkCallback cb : callbacks) {
3458 mCm.unregisterNetworkCallback(cb);
3459 }
3460 });
3461 }
3462
3463 private long durationOf(Runnable fn) {
3464 long startTime = SystemClock.elapsedRealtime();
3465 fn.run();
3466 return SystemClock.elapsedRealtime() - startTime;
3467 }
3468
3469 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3470 long timeTaken = durationOf(fn);
3471 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003472 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003473 assertTrue(msg, timeTaken <= timeLimit);
3474 }
3475
3476 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3477 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09003478 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003479 } catch (InterruptedException e) {}
3480 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003481 }
3482
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003483 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003484 public void testMobileDataAlwaysOn() throws Exception {
3485 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3486 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3487 .addTransportType(TRANSPORT_CELLULAR).build();
3488 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3489
3490 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3491 handlerThread.start();
3492 NetworkCapabilities filter = new NetworkCapabilities()
3493 .addTransportType(TRANSPORT_CELLULAR)
3494 .addCapability(NET_CAPABILITY_INTERNET);
3495 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3496 mServiceContext, "testFactory", filter);
3497 testFactory.setScoreFilter(40);
3498
3499 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003500 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003501 testFactory.register();
3502 testFactory.waitForNetworkRequests(1);
3503 assertTrue(testFactory.getMyStartRequested());
3504
3505 // Bring up wifi. The factory stops looking for a network.
3506 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003507 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3508 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003509 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003510 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003511 assertFalse(testFactory.getMyStartRequested());
3512
3513 ContentResolver cr = mServiceContext.getContentResolver();
3514
3515 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003516 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003517 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003518 testFactory.waitForNetworkRequests(2);
3519 assertTrue(testFactory.getMyStartRequested());
3520
3521 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003522 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003523 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003524 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003525 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003526 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003527 testFactory.waitForNetworkRequests(2);
3528 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3529
3530 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003531 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003532 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003533 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003534
3535 // Turn off mobile data always on and expect the request to disappear...
3536 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003537 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003538 testFactory.waitForNetworkRequests(1);
3539
3540 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003541 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003542 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003543
3544 testFactory.unregister();
3545 mCm.unregisterNetworkCallback(cellNetworkCallback);
3546 handlerThread.quit();
3547 }
3548
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003549 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003550 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003551 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003552 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003553 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3554
Erik Kline065ab6e2016-10-02 18:02:14 +09003555 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003556 String[] values = new String[] {null, "0", "1"};
3557 for (int i = 0; i < values.length; i++) {
3558 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003559 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003560 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003561 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003562 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003563 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003564 }
3565
Erik Kline065ab6e2016-10-02 18:02:14 +09003566 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003567
3568 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003569 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003570 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003571 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003572 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003573
3574 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003575 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003576 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003577 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003578 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003579
3580 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003581 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003582 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003583 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003584 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003585 }
3586
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003587 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003588 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003589 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003590 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003591
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003592 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003593 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003594
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003595 // File a request for cell to ensure it doesn't go down.
3596 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3597 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3598 .addTransportType(TRANSPORT_CELLULAR).build();
3599 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3600
3601 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3602 mCm.registerDefaultNetworkCallback(defaultCallback);
3603
3604 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3605 .addTransportType(TRANSPORT_WIFI)
3606 .addCapability(NET_CAPABILITY_VALIDATED)
3607 .build();
3608 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3609 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3610
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003611 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003612 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003613
3614 // Bring up validated cell.
3615 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3616 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003617 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3618 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003619 Network cellNetwork = mCellNetworkAgent.getNetwork();
3620
3621 // Bring up validated wifi.
3622 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3623 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003624 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3625 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003626 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3627
3628 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003629 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003630 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003631 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003632 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3633
3634 // Because avoid bad wifi is off, we don't switch to cellular.
3635 defaultCallback.assertNoCallback();
3636 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3637 NET_CAPABILITY_VALIDATED));
3638 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3639 NET_CAPABILITY_VALIDATED));
3640 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3641
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003642 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3643 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003644 tracker.configRestrictsAvoidBadWifi = false;
3645 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003646 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003647 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3648
3649 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003650 tracker.configRestrictsAvoidBadWifi = true;
3651 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003652 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003653 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3654
3655 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3656 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003657 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003658 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3659 NET_CAPABILITY_VALIDATED));
3660 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3661 NET_CAPABILITY_VALIDATED));
3662 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3663
3664 // Disconnect and reconnect wifi to clear the one-time switch above.
3665 mWiFiNetworkAgent.disconnect();
3666 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3667 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003668 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3669 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003670 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3671
3672 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003673 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003674 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003675 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003676 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3677
3678 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003679 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003680 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003681
3682 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003683 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003684 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3685 NET_CAPABILITY_VALIDATED));
3686 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3687 NET_CAPABILITY_VALIDATED));
3688 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3689
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003690 // Simulate the user turning the cellular fallback setting off and then on.
3691 // We switch to wifi and then to cell.
3692 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003693 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003694 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003695 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3696 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003697 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003698 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003699 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3700
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003701 // If cell goes down, we switch to wifi.
3702 mCellNetworkAgent.disconnect();
3703 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003704 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003705 validatedWifiCallback.assertNoCallback();
3706
3707 mCm.unregisterNetworkCallback(cellNetworkCallback);
3708 mCm.unregisterNetworkCallback(validatedWifiCallback);
3709 mCm.unregisterNetworkCallback(defaultCallback);
3710 }
3711
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003712 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003713 public void testMeteredMultipathPreferenceSetting() throws Exception {
3714 final ContentResolver cr = mServiceContext.getContentResolver();
3715 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3716 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3717
3718 for (int config : Arrays.asList(0, 3, 2)) {
3719 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3720 tracker.configMeteredMultipathPreference = config;
3721 Settings.Global.putString(cr, settingName, setting);
3722 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003723 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003724
3725 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3726 String msg = String.format("config=%d, setting=%s", config, setting);
3727 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3728 }
3729 }
3730 }
3731
Erik Kline3841a482015-11-25 12:49:38 +09003732 /**
3733 * Validate that a satisfied network request does not trigger onUnavailable() once the
3734 * time-out period expires.
3735 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003736 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003737 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3738 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3739 NetworkCapabilities.TRANSPORT_WIFI).build();
3740 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003741 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003742
3743 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3744 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003745 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003746 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003747
3748 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003749 networkCallback.assertNoCallback();
3750 }
3751
3752 /**
3753 * Validate that a satisfied network request followed by a disconnected (lost) network does
3754 * not trigger onUnavailable() once the time-out period expires.
3755 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003756 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003757 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3758 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3759 NetworkCapabilities.TRANSPORT_WIFI).build();
3760 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003761 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003762
3763 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3764 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003765 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003766 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003767 mWiFiNetworkAgent.disconnect();
3768 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3769
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003770 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003771 networkCallback.assertNoCallback();
3772 }
3773
3774 /**
3775 * Validate that when a time-out is specified for a network request the onUnavailable()
3776 * callback is called when time-out expires. Then validate that if network request is
3777 * (somehow) satisfied - the callback isn't called later.
3778 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003779 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003780 public void testTimedoutNetworkRequest() {
3781 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3782 NetworkCapabilities.TRANSPORT_WIFI).build();
3783 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003784 final int timeoutMs = 10;
3785 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003786
3787 // pass timeout and validate that UNAVAILABLE is called
3788 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3789
3790 // create a network satisfying request - validate that request not triggered
3791 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3792 mWiFiNetworkAgent.connect(false);
3793 networkCallback.assertNoCallback();
3794 }
3795
3796 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003797 * Validate that when a network request is unregistered (cancelled), no posterior event can
3798 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003799 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003800 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003801 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003802 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3803 NetworkCapabilities.TRANSPORT_WIFI).build();
3804 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003805 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003806
Hugo Benichidfb559a2016-12-20 14:57:49 +09003807 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003808 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003809 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3810 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003811 networkCallback.assertNoCallback();
3812
3813 // create a network satisfying request - validate that request not triggered
3814 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3815 mWiFiNetworkAgent.connect(false);
3816 networkCallback.assertNoCallback();
3817 }
3818
Etan Cohenddb720a2019-01-08 12:09:18 -08003819 /**
3820 * Validate the callback flow for a factory releasing a request as unfulfillable.
3821 */
3822 @Test
3823 public void testUnfulfillableNetworkRequest() throws Exception {
3824 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3825 NetworkCapabilities.TRANSPORT_WIFI).build();
3826 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3827
3828 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3829 handlerThread.start();
3830 NetworkCapabilities filter = new NetworkCapabilities()
3831 .addTransportType(TRANSPORT_WIFI)
3832 .addCapability(NET_CAPABILITY_INTERNET);
3833 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3834 mServiceContext, "testFactory", filter);
3835 testFactory.setScoreFilter(40);
3836
3837 // Register the factory and expect it to receive the default request.
Chalard Jean05ab6812018-05-02 21:14:54 +09003838 testFactory.expectAddRequestsWithScores(0); // default request score is 0, not served yet
Etan Cohenddb720a2019-01-08 12:09:18 -08003839 testFactory.register();
3840 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3841
3842 assertEquals(1, requests.size()); // have 1 request at this point
3843 int origRequestId = requests.valueAt(0).requestId;
3844
3845 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003846 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003847 mCm.requestNetwork(nr, networkCallback);
3848 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3849
3850 int newRequestId = 0;
3851 for (int i = 0; i < requests.size(); ++i) {
3852 if (requests.valueAt(i).requestId != origRequestId) {
3853 newRequestId = requests.valueAt(i).requestId;
3854 break;
3855 }
3856 }
3857
3858 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
3859 testFactory.expectRemoveRequests(1);
3860 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3861 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3862 testFactory.waitForRequests();
3863
Etan Cohen9b09a162019-04-16 15:07:55 -07003864 // unregister network callback - a no-op, but should not fail
3865 mCm.unregisterNetworkCallback(networkCallback);
3866
Etan Cohenddb720a2019-01-08 12:09:18 -08003867 testFactory.unregister();
3868 handlerThread.quit();
3869 }
3870
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003871 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3872
3873 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3874
3875 private class CallbackValue {
3876 public CallbackType callbackType;
3877 public int error;
3878
3879 public CallbackValue(CallbackType type) {
3880 this.callbackType = type;
3881 this.error = PacketKeepalive.SUCCESS;
3882 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3883 }
3884
3885 public CallbackValue(CallbackType type, int error) {
3886 this.callbackType = type;
3887 this.error = error;
3888 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3889 }
3890
3891 @Override
3892 public boolean equals(Object o) {
3893 return o instanceof CallbackValue &&
3894 this.callbackType == ((CallbackValue) o).callbackType &&
3895 this.error == ((CallbackValue) o).error;
3896 }
3897
3898 @Override
3899 public String toString() {
3900 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3901 }
3902 }
3903
junyulai7c469172019-01-16 20:23:34 +08003904 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003905
3906 @Override
3907 public void onStarted() {
3908 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3909 }
3910
3911 @Override
3912 public void onStopped() {
3913 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3914 }
3915
3916 @Override
3917 public void onError(int error) {
3918 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3919 }
3920
3921 private void expectCallback(CallbackValue callbackValue) {
3922 try {
3923 assertEquals(
3924 callbackValue,
3925 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3926 } catch (InterruptedException e) {
3927 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3928 }
3929 }
3930
3931 public void expectStarted() {
3932 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3933 }
3934
3935 public void expectStopped() {
3936 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3937 }
3938
3939 public void expectError(int error) {
3940 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3941 }
3942 }
3943
junyulai48eac1d42018-12-27 17:25:29 +08003944 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3945
3946 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3947
3948 private class CallbackValue {
3949 public CallbackType callbackType;
3950 public int error;
3951
3952 CallbackValue(CallbackType type) {
3953 this.callbackType = type;
3954 this.error = SocketKeepalive.SUCCESS;
3955 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3956 }
3957
3958 CallbackValue(CallbackType type, int error) {
3959 this.callbackType = type;
3960 this.error = error;
3961 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3962 }
3963
3964 @Override
3965 public boolean equals(Object o) {
3966 return o instanceof CallbackValue
3967 && this.callbackType == ((CallbackValue) o).callbackType
3968 && this.error == ((CallbackValue) o).error;
3969 }
3970
3971 @Override
3972 public String toString() {
3973 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3974 error);
3975 }
3976 }
3977
3978 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003979 private final Executor mExecutor;
3980
3981 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3982 mExecutor = executor;
3983 }
junyulai48eac1d42018-12-27 17:25:29 +08003984
3985 @Override
3986 public void onStarted() {
3987 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3988 }
3989
3990 @Override
3991 public void onStopped() {
3992 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3993 }
3994
3995 @Override
3996 public void onError(int error) {
3997 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3998 }
3999
4000 private void expectCallback(CallbackValue callbackValue) {
4001 try {
4002 assertEquals(
4003 callbackValue,
4004 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4005 } catch (InterruptedException e) {
4006 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
4007 }
4008 }
4009
4010 public void expectStarted() {
4011 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4012 }
4013
4014 public void expectStopped() {
4015 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4016 }
4017
4018 public void expectError(int error) {
4019 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4020 }
junyulai7c469172019-01-16 20:23:34 +08004021
4022 public void assertNoCallback() {
4023 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
4024 CallbackValue cv = mCallbacks.peek();
4025 assertNull("Unexpected callback: " + cv, cv);
4026 }
junyulai48eac1d42018-12-27 17:25:29 +08004027 }
4028
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004029 private Network connectKeepaliveNetwork(LinkProperties lp) {
4030 // Ensure the network is disconnected before we do anything.
4031 if (mWiFiNetworkAgent != null) {
4032 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
4033 }
4034
4035 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4036 ConditionVariable cv = waitForConnectivityBroadcasts(1);
4037 mWiFiNetworkAgent.connect(true);
4038 waitFor(cv);
4039 verifyActiveNetwork(TRANSPORT_WIFI);
4040 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09004041 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004042 return mWiFiNetworkAgent.getNetwork();
4043 }
4044
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004045 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004046 public void testPacketKeepalives() throws Exception {
4047 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4048 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4049 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4050 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4051 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4052
Nathan Harold63dd8132018-02-14 13:09:45 -08004053 final int validKaInterval = 15;
4054 final int invalidKaInterval = 9;
4055
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004056 LinkProperties lp = new LinkProperties();
4057 lp.setInterfaceName("wlan12");
4058 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4059 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4060 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4061 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4062
4063 Network notMyNet = new Network(61234);
4064 Network myNet = connectKeepaliveNetwork(lp);
4065
4066 TestKeepaliveCallback callback = new TestKeepaliveCallback();
4067 PacketKeepalive ka;
4068
4069 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08004070 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004071 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4072
Nathan Harold63dd8132018-02-14 13:09:45 -08004073 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004074 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4075
Nathan Harold63dd8132018-02-14 13:09:45 -08004076 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004077 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4078
Nathan Harold63dd8132018-02-14 13:09:45 -08004079 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004080 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4081
Nathan Harold63dd8132018-02-14 13:09:45 -08004082 // NAT-T is only supported for IPv4.
4083 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4084 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004085
Nathan Harold63dd8132018-02-14 13:09:45 -08004086 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004087 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4088
Nathan Harold63dd8132018-02-14 13:09:45 -08004089 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004090 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4091
Nathan Harold63dd8132018-02-14 13:09:45 -08004092 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004093 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4094
Nathan Harold63dd8132018-02-14 13:09:45 -08004095 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004096 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4097
4098 // Check that a started keepalive can be stopped.
4099 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08004100 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004101 callback.expectStarted();
4102 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
4103 ka.stop();
4104 callback.expectStopped();
4105
4106 // Check that deleting the IP address stops the keepalive.
4107 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08004108 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004109 callback.expectStarted();
4110 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4111 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4112 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4113 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4114 mWiFiNetworkAgent.sendLinkProperties(lp);
4115
4116 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004117 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004118 callback.expectStarted();
4119 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004120 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004121 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4122
4123 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004124 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004125 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004126 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004127 ka.stop();
4128
4129 // Reconnect.
4130 myNet = connectKeepaliveNetwork(lp);
4131 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
4132
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004133 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4134 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004135 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004136 callback.expectStarted();
4137
4138 // The second one gets slot 2.
4139 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4140 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004141 PacketKeepalive ka2 = mCm.startNattKeepalive(
4142 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004143 callback2.expectStarted();
4144
4145 // Now stop the first one and create a third. This also gets slot 1.
4146 ka.stop();
4147 callback.expectStopped();
4148
4149 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4150 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004151 PacketKeepalive ka3 = mCm.startNattKeepalive(
4152 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004153 callback3.expectStarted();
4154
4155 ka2.stop();
4156 callback2.expectStopped();
4157
4158 ka3.stop();
4159 callback3.expectStopped();
4160 }
Udam Sainib7c24872016-01-04 12:16:14 -08004161
junyulaiafe9b492019-03-19 18:50:23 +08004162 @FunctionalInterface
4163 private interface ThrowingConsumer<T> {
4164 void accept(T t) throws Exception;
4165 }
4166
Xiao Maa4637112019-02-07 15:03:57 +09004167 // Helper method to prepare the executor and run test
junyulaiafe9b492019-03-19 18:50:23 +08004168 private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
junyulai06835112019-01-03 18:50:15 +08004169 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004170 final Executor executorInline = (Runnable r) -> r.run();
4171 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08004172 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004173 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004174 }
junyulai06835112019-01-03 18:50:15 +08004175
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004176 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004177 public void testNattSocketKeepalives() throws Exception {
4178 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4179 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08004180 }
4181
4182 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004183 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08004184 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004185 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004186 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4187 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4188 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4189 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4190 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4191
4192 final int validKaInterval = 15;
4193 final int invalidKaInterval = 9;
4194
4195 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004196 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4197 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004198
junyulai48eac1d42018-12-27 17:25:29 +08004199 LinkProperties lp = new LinkProperties();
4200 lp.setInterfaceName("wlan12");
4201 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4202 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4203 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4204 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4205
4206 Network notMyNet = new Network(61234);
4207 Network myNet = connectKeepaliveNetwork(lp);
4208
junyulai7c469172019-01-16 20:23:34 +08004209 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004210
4211 // Attempt to start keepalives with invalid parameters and check for errors.
4212 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004213 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4214 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4215 ka.start(validKaInterval);
4216 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4217 }
junyulai48eac1d42018-12-27 17:25:29 +08004218
4219 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004220 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4221 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4222 ka.start(invalidKaInterval);
4223 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4224 }
junyulai48eac1d42018-12-27 17:25:29 +08004225
4226 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004227 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4228 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4229 ka.start(validKaInterval);
4230 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4231 }
junyulai48eac1d42018-12-27 17:25:29 +08004232
4233 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004234 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4235 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4236 ka.start(validKaInterval);
4237 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4238 }
junyulai48eac1d42018-12-27 17:25:29 +08004239
4240 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004241 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4242 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4243 ka.start(validKaInterval);
4244 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4245 }
junyulai48eac1d42018-12-27 17:25:29 +08004246
4247 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004248 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4249 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4250 ka.start(validKaInterval);
4251 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4252 }
junyulai48eac1d42018-12-27 17:25:29 +08004253
4254 // Check that a started keepalive can be stopped.
4255 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004256 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4257 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4258 ka.start(validKaInterval);
4259 callback.expectStarted();
4260 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4261 ka.stop();
4262 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004263
junyulai0c666972019-03-04 22:45:36 +08004264 // Check that keepalive could be restarted.
4265 ka.start(validKaInterval);
4266 callback.expectStarted();
4267 ka.stop();
4268 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004269
junyulai0c666972019-03-04 22:45:36 +08004270 // Check that keepalive can be restarted without waiting for callback.
4271 ka.start(validKaInterval);
4272 callback.expectStarted();
4273 ka.stop();
4274 ka.start(validKaInterval);
4275 callback.expectStopped();
4276 callback.expectStarted();
4277 ka.stop();
4278 callback.expectStopped();
junyulaicecd4a32019-04-16 19:32:32 +08004279
4280 // Check that the same NATT socket cannot be used by 2 keepalives.
4281 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4282 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4283 // Check that second keepalive cannot be started if the first one is running.
4284 ka.start(validKaInterval);
4285 callback.expectStarted();
4286 ka2.start(validKaInterval);
4287 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4288 ka.stop();
4289 callback.expectStopped();
4290
4291 // Check that second keepalive can be started/stopped normally if the first one is
4292 // stopped.
4293 ka2.start(validKaInterval);
4294 callback.expectStarted();
4295 ka2.stop();
4296 callback.expectStopped();
4297 }
junyulai0c666972019-03-04 22:45:36 +08004298 }
junyulai7c469172019-01-16 20:23:34 +08004299
junyulai48eac1d42018-12-27 17:25:29 +08004300 // Check that deleting the IP address stops the keepalive.
4301 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004302 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4303 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4304 ka.start(validKaInterval);
4305 callback.expectStarted();
4306 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4307 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4308 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4309 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4310 mWiFiNetworkAgent.sendLinkProperties(lp);
4311 }
junyulai48eac1d42018-12-27 17:25:29 +08004312
4313 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004314 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4315 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4316 ka.start(validKaInterval);
4317 callback.expectStarted();
4318 mWiFiNetworkAgent.disconnect();
4319 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4320 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004321
junyulai0c666972019-03-04 22:45:36 +08004322 // ... and that stopping it after that has no adverse effects.
4323 waitForIdle();
4324 final Network myNetAlias = myNet;
4325 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4326 ka.stop();
4327 callback.assertNoCallback();
4328 }
junyulai48eac1d42018-12-27 17:25:29 +08004329
4330 // Reconnect.
4331 myNet = connectKeepaliveNetwork(lp);
4332 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4333
4334 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4335 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004336 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004337 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4338 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4339 ka.start(validKaInterval);
4340 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004341
junyulai0c666972019-03-04 22:45:36 +08004342 // The second one gets slot 2.
4343 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004344 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4345 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004346 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4347 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4348 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4349 ka2.start(validKaInterval);
4350 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004351
junyulai0c666972019-03-04 22:45:36 +08004352 ka.stop();
4353 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004354
junyulai0c666972019-03-04 22:45:36 +08004355 ka2.stop();
4356 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004357
junyulai0c666972019-03-04 22:45:36 +08004358 testSocket.close();
4359 testSocket2.close();
4360 }
junyulaicecd4a32019-04-16 19:32:32 +08004361
4362 // Check that the closed socket cannot be used to start keepalive.
4363 ka.start(validKaInterval);
4364 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
junyulai0c666972019-03-04 22:45:36 +08004365 }
junyulai06835112019-01-03 18:50:15 +08004366
junyulai15178152019-03-27 11:00:37 +08004367 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004368 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4369 // assertFalse(isUdpPortInUse(srcPort));
4370 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004371
junyulai06835112019-01-03 18:50:15 +08004372 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004373 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Xiao Maa4637112019-02-07 15:03:57 +09004374 mWiFiNetworkAgent = null;
4375 }
4376
4377 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004378 public void testTcpSocketKeepalives() throws Exception {
4379 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004380 }
4381
4382 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4383 final int srcPortV4 = 12345;
4384 final int srcPortV6 = 23456;
4385 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4386 final InetAddress myIPv6 = InetAddress.getByName("::1");
4387
4388 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004389
4390 final LinkProperties lp = new LinkProperties();
4391 lp.setInterfaceName("wlan12");
4392 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4393 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4394 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4395 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4396
4397 final Network notMyNet = new Network(61234);
4398 final Network myNet = connectKeepaliveNetwork(lp);
4399
4400 final Socket testSocketV4 = new Socket();
4401 final Socket testSocketV6 = new Socket();
4402
junyulai7c469172019-01-16 20:23:34 +08004403 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004404
4405 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4406 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004407 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4408 notMyNet, testSocketV4, executor, callback)) {
4409 ka.start(validKaInterval);
4410 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4411 }
Xiao Maa4637112019-02-07 15:03:57 +09004412
4413 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004414 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4415 myNet, testSocketV4, executor, callback)) {
4416 ka.start(validKaInterval);
4417 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4418 }
Xiao Maa4637112019-02-07 15:03:57 +09004419
4420 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004421 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4422 myNet, testSocketV6, executor, callback)) {
4423 ka.start(validKaInterval);
4424 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4425 }
Xiao Maa4637112019-02-07 15:03:57 +09004426
4427 // Bind the socket address
4428 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4429 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4430
4431 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004432 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4433 myNet, testSocketV4, executor, callback)) {
4434 ka.start(validKaInterval);
4435 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4436 }
Xiao Maa4637112019-02-07 15:03:57 +09004437
4438 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004439 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4440 myNet, testSocketV6, executor, callback)) {
4441 ka.start(validKaInterval);
4442 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4443 }
Xiao Maa4637112019-02-07 15:03:57 +09004444
4445 testSocketV4.close();
4446 testSocketV6.close();
4447
4448 mWiFiNetworkAgent.disconnect();
4449 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4450 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004451 }
4452
junyulai0c666972019-03-04 22:45:36 +08004453 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004454 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4455 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4456 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4457 final int validKaInterval = 15;
4458
4459 // Prepare the target network.
4460 LinkProperties lp = new LinkProperties();
4461 lp.setInterfaceName("wlan12");
4462 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4463 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4464 Network myNet = connectKeepaliveNetwork(lp);
4465 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4466 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4467
4468 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4469
4470 // Prepare the target file descriptor, keep only one instance.
4471 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004472 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4473 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004474 final ParcelFileDescriptor testPfd =
4475 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4476 testSocket.close();
4477 assertTrue(isUdpPortInUse(srcPort));
4478
4479 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4480 // block.
4481 try (SocketKeepalive ka = mCm.createNattKeepalive(
4482 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4483 ka.start(validKaInterval);
4484 callback.expectStarted();
4485 ka.stop();
4486 callback.expectStopped();
4487 }
4488
4489 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4490 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4491 // address.
4492 assertTrue(isUdpPortInUse(srcPort));
4493 final InetSocketAddress sa =
4494 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4495 assertEquals(anyIPv4, sa.getAddress());
4496
4497 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004498 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4499 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004500
4501 mWiFiNetworkAgent.disconnect();
4502 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4503 mWiFiNetworkAgent = null;
4504 }
4505
4506 private static boolean isUdpPortInUse(int port) {
4507 try (DatagramSocket ignored = new DatagramSocket(port)) {
4508 return false;
4509 } catch (IOException ignored) {
4510 return true;
4511 }
4512 }
4513
junyulai48eac1d42018-12-27 17:25:29 +08004514 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004515 public void testGetCaptivePortalServerUrl() throws Exception {
4516 String url = mCm.getCaptivePortalServerUrl();
4517 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4518 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004519
4520 private static class TestNetworkPinner extends NetworkPinner {
4521 public static boolean awaitPin(int timeoutMs) {
4522 synchronized(sLock) {
4523 if (sNetwork == null) {
4524 try {
4525 sLock.wait(timeoutMs);
4526 } catch (InterruptedException e) {}
4527 }
4528 return sNetwork != null;
4529 }
4530 }
4531
4532 public static boolean awaitUnpin(int timeoutMs) {
4533 synchronized(sLock) {
4534 if (sNetwork != null) {
4535 try {
4536 sLock.wait(timeoutMs);
4537 } catch (InterruptedException e) {}
4538 }
4539 return sNetwork == null;
4540 }
4541 }
4542 }
4543
4544 private void assertPinnedToWifiWithCellDefault() {
4545 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4546 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4547 }
4548
4549 private void assertPinnedToWifiWithWifiDefault() {
4550 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4551 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4552 }
4553
4554 private void assertNotPinnedToWifi() {
4555 assertNull(mCm.getBoundNetworkForProcess());
4556 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4557 }
4558
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004559 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004560 public void testNetworkPinner() {
4561 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4562 .addTransportType(TRANSPORT_WIFI)
4563 .build();
4564 assertNull(mCm.getBoundNetworkForProcess());
4565
4566 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4567 assertNull(mCm.getBoundNetworkForProcess());
4568
4569 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4570 mCellNetworkAgent.connect(true);
4571 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4572 mWiFiNetworkAgent.connect(false);
4573
4574 // When wi-fi connects, expect to be pinned.
4575 assertTrue(TestNetworkPinner.awaitPin(100));
4576 assertPinnedToWifiWithCellDefault();
4577
4578 // Disconnect and expect the pin to drop.
4579 mWiFiNetworkAgent.disconnect();
4580 assertTrue(TestNetworkPinner.awaitUnpin(100));
4581 assertNotPinnedToWifi();
4582
4583 // Reconnecting does not cause the pin to come back.
4584 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4585 mWiFiNetworkAgent.connect(false);
4586 assertFalse(TestNetworkPinner.awaitPin(100));
4587 assertNotPinnedToWifi();
4588
4589 // Pinning while connected causes the pin to take effect immediately.
4590 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4591 assertTrue(TestNetworkPinner.awaitPin(100));
4592 assertPinnedToWifiWithCellDefault();
4593
4594 // Explicitly unpin and expect to use the default network again.
4595 TestNetworkPinner.unpin();
4596 assertNotPinnedToWifi();
4597
4598 // Disconnect cell and wifi.
4599 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4600 mCellNetworkAgent.disconnect();
4601 mWiFiNetworkAgent.disconnect();
4602 waitFor(cv);
4603
4604 // Pinning takes effect even if the pinned network is the default when the pin is set...
4605 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4606 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4607 mWiFiNetworkAgent.connect(false);
4608 assertTrue(TestNetworkPinner.awaitPin(100));
4609 assertPinnedToWifiWithWifiDefault();
4610
4611 // ... and is maintained even when that network is no longer the default.
4612 cv = waitForConnectivityBroadcasts(1);
4613 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4614 mCellNetworkAgent.connect(true);
4615 waitFor(cv);
4616 assertPinnedToWifiWithCellDefault();
4617 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004618
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004619 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004620 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004621 // We can only have 99 callbacks, because MultipathPolicyTracker is
4622 // already one of them.
4623 final int MAX_REQUESTS = 99;
4624 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004625 final int INTENTS = 10;
4626 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4627
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004628 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004629 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004630
Hugo Benichi893a7622017-09-29 09:34:08 +09004631 int j = 0;
4632 while (j++ < CALLBACKS / 2) {
4633 NetworkCallback cb = new NetworkCallback();
4634 mCm.requestNetwork(networkRequest, cb);
4635 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004636 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004637 while (j++ < CALLBACKS) {
4638 NetworkCallback cb = new NetworkCallback();
4639 mCm.registerNetworkCallback(networkRequest, cb);
4640 registered.add(cb);
4641 }
4642 j = 0;
4643 while (j++ < INTENTS / 2) {
4644 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4645 mCm.requestNetwork(networkRequest, pi);
4646 registered.add(pi);
4647 }
4648 while (j++ < INTENTS) {
4649 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4650 mCm.registerNetworkCallback(networkRequest, pi);
4651 registered.add(pi);
4652 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004653
Hugo Benichi893a7622017-09-29 09:34:08 +09004654 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004655 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09004656 mCm.requestNetwork(networkRequest, new NetworkCallback());
4657 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09004658 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09004659 try {
4660 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4661 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4662 } catch (TooManyRequestsException expected) {}
4663 try {
4664 mCm.requestNetwork(networkRequest,
4665 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4666 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4667 } catch (TooManyRequestsException expected) {}
4668 try {
4669 mCm.registerNetworkCallback(networkRequest,
4670 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4671 fail("Registering " + MAX_REQUESTS
4672 + " PendingIntent callbacks did not throw exception");
4673 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004674
Hugo Benichi893a7622017-09-29 09:34:08 +09004675 for (Object o : registered) {
4676 if (o instanceof NetworkCallback) {
4677 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004678 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004679 if (o instanceof PendingIntent) {
4680 mCm.unregisterNetworkCallback((PendingIntent)o);
4681 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004682 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004683 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004684
4685 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4686 for (int i = 0; i < MAX_REQUESTS; i++) {
4687 NetworkCallback networkCallback = new NetworkCallback();
4688 mCm.requestNetwork(networkRequest, networkCallback);
4689 mCm.unregisterNetworkCallback(networkCallback);
4690 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004691 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004692
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004693 for (int i = 0; i < MAX_REQUESTS; i++) {
4694 NetworkCallback networkCallback = new NetworkCallback();
4695 mCm.registerNetworkCallback(networkRequest, networkCallback);
4696 mCm.unregisterNetworkCallback(networkCallback);
4697 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004698 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004699
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004700 for (int i = 0; i < MAX_REQUESTS; i++) {
4701 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004702 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004703 mCm.requestNetwork(networkRequest, pendingIntent);
4704 mCm.unregisterNetworkCallback(pendingIntent);
4705 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004706 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004707
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004708 for (int i = 0; i < MAX_REQUESTS; i++) {
4709 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004710 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004711 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4712 mCm.unregisterNetworkCallback(pendingIntent);
4713 }
4714 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004715
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004716 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004717 public void testNetworkInfoOfTypeNone() {
4718 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4719
4720 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09004721 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004722 assertNull(mCm.getActiveNetworkInfo());
4723
4724 Network[] allNetworks = mCm.getAllNetworks();
4725 assertLength(1, allNetworks);
4726 Network network = allNetworks[0];
4727 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4728 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4729
4730 final NetworkRequest request =
4731 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4732 final TestNetworkCallback callback = new TestNetworkCallback();
4733 mCm.registerNetworkCallback(request, callback);
4734
Hugo Benichic1014502017-07-19 10:10:52 +09004735 // Bring up wifi aware network.
4736 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004737 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004738
4739 assertNull(mCm.getActiveNetworkInfo());
4740 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004741 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004742 // of this test. Fix it and uncomment the assert below.
4743 //assertEmpty(mCm.getAllNetworkInfo());
4744
Hugo Benichic1014502017-07-19 10:10:52 +09004745 // Disconnect wifi aware network.
4746 wifiAware.disconnect();
4747 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004748 mCm.unregisterNetworkCallback(callback);
4749
4750 verifyNoNetwork();
4751 if (broadcastCV.block(10)) {
4752 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4753 }
4754 }
4755
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004756 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004757 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4758 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4759 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4760 assertNull(mCm.getNetworkForType(TYPE_NONE));
4761 assertNull(mCm.getLinkProperties(TYPE_NONE));
4762 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4763
4764 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4765 IllegalArgumentException.class);
4766
4767 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4768 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4769 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4770 // TODO: let test context have configuration application target sdk version
4771 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4772 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4773 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4774 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4775 }
4776
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004777 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01004778 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4779 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4780 .addTransportType(TRANSPORT_WIFI).build();
4781 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4782 mCm.registerNetworkCallback(networkRequest, networkCallback);
4783
4784 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004785 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004786 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4787 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4788 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4789 lp.addLinkAddress(myIpv4Address);
4790 lp.addRoute(myIpv4DefaultRoute);
4791
4792 // Verify direct routes are added when network agent is first registered in
4793 // ConnectivityService.
4794 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4795 networkAgent.connect(true);
4796 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4797 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4798 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4799 networkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004800 networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004801 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4802 networkCallback.assertNoCallback();
4803 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4804 Arrays.asList(myIpv4DefaultRoute));
4805 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4806 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4807
4808 // Verify direct routes are added during subsequent link properties updates.
4809 LinkProperties newLp = new LinkProperties(lp);
4810 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4811 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4812 newLp.addLinkAddress(myIpv6Address1);
4813 newLp.addLinkAddress(myIpv6Address2);
4814 networkAgent.sendLinkProperties(newLp);
4815 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4816 networkCallback.assertNoCallback();
4817 checkDirectlyConnectedRoutes(cbi.arg,
4818 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4819 Arrays.asList(myIpv4DefaultRoute));
4820 mCm.unregisterNetworkCallback(networkCallback);
4821 }
4822
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004823 @Test
4824 public void testStatsIfacesChanged() throws Exception {
4825 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004826 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4827
Varun Anandd33cbc62019-02-07 14:13:13 -08004828 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4829 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4830
4831 LinkProperties cellLp = new LinkProperties();
4832 cellLp.setInterfaceName(MOBILE_IFNAME);
4833 LinkProperties wifiLp = new LinkProperties();
4834 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004835
4836 // Simple connection should have updated ifaces
4837 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004838 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004839 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004840 verify(mStatsService, atLeastOnce())
4841 .forceUpdateIfaces(
4842 eq(onlyCell),
4843 eq(new VpnInfo[0]),
4844 any(NetworkState[].class),
4845 eq(MOBILE_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004846 reset(mStatsService);
4847
4848 // Default network switch should update ifaces.
4849 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004850 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004851 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004852 assertEquals(wifiLp, mService.getActiveLinkProperties());
4853 verify(mStatsService, atLeastOnce())
4854 .forceUpdateIfaces(
4855 eq(onlyWifi),
4856 eq(new VpnInfo[0]),
4857 any(NetworkState[].class),
4858 eq(WIFI_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004859 reset(mStatsService);
4860
4861 // Disconnect should update ifaces.
4862 mWiFiNetworkAgent.disconnect();
4863 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004864 verify(mStatsService, atLeastOnce())
4865 .forceUpdateIfaces(
4866 eq(onlyCell),
4867 eq(new VpnInfo[0]),
4868 any(NetworkState[].class),
4869 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004870 reset(mStatsService);
4871
4872 // Metered change should update ifaces
4873 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4874 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004875 verify(mStatsService, atLeastOnce())
4876 .forceUpdateIfaces(
4877 eq(onlyCell),
4878 eq(new VpnInfo[0]),
4879 any(NetworkState[].class),
4880 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004881 reset(mStatsService);
4882
4883 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4884 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004885 verify(mStatsService, atLeastOnce())
4886 .forceUpdateIfaces(
4887 eq(onlyCell),
4888 eq(new VpnInfo[0]),
4889 any(NetworkState[].class),
4890 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004891 reset(mStatsService);
4892
4893 // Captive portal change shouldn't update ifaces
4894 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4895 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004896 verify(mStatsService, never())
4897 .forceUpdateIfaces(
4898 eq(onlyCell),
4899 eq(new VpnInfo[0]),
4900 any(NetworkState[].class),
4901 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004902 reset(mStatsService);
4903
4904 // Roaming change should update ifaces
4905 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4906 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004907 verify(mStatsService, atLeastOnce())
4908 .forceUpdateIfaces(
4909 eq(onlyCell),
4910 eq(new VpnInfo[0]),
4911 any(NetworkState[].class),
4912 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004913 reset(mStatsService);
4914 }
4915
Erik Klinee89953b2018-01-11 16:11:10 +09004916 @Test
4917 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004918 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004919
4920 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004921 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004922
Erik Klinee89953b2018-01-11 16:11:10 +09004923 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4924 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004925 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004926 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004927
4928 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004929 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004930 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4931 // "is-reachable" testing in order to not program netd with unreachable
4932 // nameservers that it might try repeated to validate.
4933 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004934 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4935 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004936 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004937 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4938 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004939 mCellNetworkAgent.sendLinkProperties(cellLp);
4940 mCellNetworkAgent.connect(false);
4941 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004942
4943 verify(mMockDnsResolver, times(1)).createNetworkCache(
4944 eq(mCellNetworkAgent.getNetwork().netId));
4945 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004946 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004947 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004948
4949 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4950 mCellNetworkAgent.sendLinkProperties(cellLp);
4951 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004952 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004953 mResolverParamsParcelCaptor.capture());
4954 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4955 assertEquals(1, resolvrParams.servers.length);
4956 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004957 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004958 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004959 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004960
4961 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4962 mCellNetworkAgent.sendLinkProperties(cellLp);
4963 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004964 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004965 mResolverParamsParcelCaptor.capture());
4966 resolvrParams = mResolverParamsParcelCaptor.getValue();
4967 assertEquals(2, resolvrParams.servers.length);
4968 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004969 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004970 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004971 assertEquals(2, resolvrParams.tlsServers.length);
4972 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004973 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004974 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004975
4976 final String TLS_SPECIFIER = "tls.example.com";
4977 final String TLS_SERVER6 = "2001:db8:53::53";
4978 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4979 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004980 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4981 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4982
Erik Kline117e7f32018-03-04 21:01:01 +09004983 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004984 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004985 mResolverParamsParcelCaptor.capture());
4986 resolvrParams = mResolverParamsParcelCaptor.getValue();
4987 assertEquals(2, resolvrParams.servers.length);
4988 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004989 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004990 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004991 }
4992
Erik Kline79c6d052018-03-21 07:18:33 -07004993 @Test
4994 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004995 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004996 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004997
4998 // The default on Android is opportunistic mode ("Automatic").
4999 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5000
dalyk1fcb7392018-03-05 12:42:22 -05005001 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5002 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5003 .addTransportType(TRANSPORT_CELLULAR).build();
5004 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5005
Erik Kline79c6d052018-03-21 07:18:33 -07005006 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5007 waitForIdle();
5008 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08005009 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005010 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005011
5012 final LinkProperties cellLp = new LinkProperties();
5013 cellLp.setInterfaceName(MOBILE_IFNAME);
5014 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5015 // "is-reachable" testing in order to not program netd with unreachable
5016 // nameservers that it might try repeated to validate.
5017 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
5018 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5019 MOBILE_IFNAME));
5020 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
5021 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5022 MOBILE_IFNAME));
5023 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5024 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5025
5026 mCellNetworkAgent.sendLinkProperties(cellLp);
5027 mCellNetworkAgent.connect(false);
5028 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005029 verify(mMockDnsResolver, times(1)).createNetworkCache(
5030 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08005031 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005032 mResolverParamsParcelCaptor.capture());
5033 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5034 assertEquals(2, resolvrParams.tlsServers.length);
5035 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005036 new String[]{"2001:db8::1", "192.0.2.1"}));
5037 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08005038 assertEquals(2, resolvrParams.tlsServers.length);
5039 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005040 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005041 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005042 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5043 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5044 mCellNetworkAgent);
5045 CallbackInfo cbi = cellNetworkCallback.expectCallback(
5046 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005047 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005048 cellNetworkCallback.assertNoCallback();
5049 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5050 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07005051
5052 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005053 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005054 mResolverParamsParcelCaptor.capture());
5055 resolvrParams = mResolverParamsParcelCaptor.getValue();
5056 assertEquals(2, resolvrParams.servers.length);
5057 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline79c6d052018-03-21 07:18:33 -07005058 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005059 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005060 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005061
5062 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005063 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005064 mResolverParamsParcelCaptor.capture());
5065 resolvrParams = mResolverParamsParcelCaptor.getValue();
5066 assertEquals(2, resolvrParams.servers.length);
5067 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline79c6d052018-03-21 07:18:33 -07005068 new String[]{"2001:db8::1", "192.0.2.1"}));
waynema13516842019-03-12 18:13:49 +08005069 assertEquals(2, resolvrParams.tlsServers.length);
5070 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005071 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005072 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005073 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005074
dalyk1fcb7392018-03-05 12:42:22 -05005075 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5076 // Can't test dns configuration for strict mode without properly mocking
5077 // out the DNS lookups, but can test that LinkProperties is updated.
5078 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5079 mCellNetworkAgent);
5080 cellNetworkCallback.assertNoCallback();
5081 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5082 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
5083 }
5084
5085 @Test
5086 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5087 // The default on Android is opportunistic mode ("Automatic").
5088 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5089
5090 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5091 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5092 .addTransportType(TRANSPORT_CELLULAR).build();
5093 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5094
5095 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5096 waitForIdle();
5097 LinkProperties lp = new LinkProperties();
5098 mCellNetworkAgent.sendLinkProperties(lp);
5099 mCellNetworkAgent.connect(false);
5100 waitForIdle();
5101 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5102 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5103 mCellNetworkAgent);
5104 CallbackInfo cbi = cellNetworkCallback.expectCallback(
5105 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005106 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005107 cellNetworkCallback.assertNoCallback();
5108 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5109 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5110 Set<InetAddress> dnsServers = new HashSet<>();
5111 checkDnsServers(cbi.arg, dnsServers);
5112
5113 // Send a validation event for a server that is not part of the current
5114 // resolver config. The validation event should be ignored.
5115 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5116 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5117 cellNetworkCallback.assertNoCallback();
5118
5119 // Add a dns server to the LinkProperties.
5120 LinkProperties lp2 = new LinkProperties(lp);
5121 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5122 mCellNetworkAgent.sendLinkProperties(lp2);
5123 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5124 mCellNetworkAgent);
5125 cellNetworkCallback.assertNoCallback();
5126 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5127 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5128 dnsServers.add(InetAddress.getByName("145.100.185.16"));
5129 checkDnsServers(cbi.arg, dnsServers);
5130
5131 // Send a validation event containing a hostname that is not part of
5132 // the current resolver config. The validation event should be ignored.
5133 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5134 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5135 cellNetworkCallback.assertNoCallback();
5136
5137 // Send a validation event where validation failed.
5138 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5139 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5140 cellNetworkCallback.assertNoCallback();
5141
5142 // Send a validation event where validation succeeded for a server in
5143 // the current resolver config. A LinkProperties callback with updated
5144 // private dns fields should be sent.
5145 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5146 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
5147 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5148 mCellNetworkAgent);
5149 cellNetworkCallback.assertNoCallback();
5150 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5151 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5152 checkDnsServers(cbi.arg, dnsServers);
5153
5154 // The private dns fields in LinkProperties should be preserved when
5155 // the network agent sends unrelated changes.
5156 LinkProperties lp3 = new LinkProperties(lp2);
5157 lp3.setMtu(1300);
5158 mCellNetworkAgent.sendLinkProperties(lp3);
5159 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5160 mCellNetworkAgent);
5161 cellNetworkCallback.assertNoCallback();
5162 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5163 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5164 checkDnsServers(cbi.arg, dnsServers);
5165 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
5166
5167 // Removing the only validated server should affect the private dns
5168 // fields in LinkProperties.
5169 LinkProperties lp4 = new LinkProperties(lp3);
5170 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5171 mCellNetworkAgent.sendLinkProperties(lp4);
5172 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5173 mCellNetworkAgent);
5174 cellNetworkCallback.assertNoCallback();
5175 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5176 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5177 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
5178 checkDnsServers(cbi.arg, dnsServers);
5179 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005180 }
5181
Rubin Xu1bb5c082017-09-05 18:40:49 +01005182 private void checkDirectlyConnectedRoutes(Object callbackObj,
5183 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5184 assertTrue(callbackObj instanceof LinkProperties);
5185 LinkProperties lp = (LinkProperties) callbackObj;
5186
5187 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5188 expectedRoutes.addAll(otherRoutes);
5189 for (LinkAddress address : linkAddresses) {
5190 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5191 // Duplicates in linkAddresses are considered failures
5192 assertTrue(expectedRoutes.add(localRoute));
5193 }
5194 List<RouteInfo> observedRoutes = lp.getRoutes();
5195 assertEquals(expectedRoutes.size(), observedRoutes.size());
5196 assertTrue(observedRoutes.containsAll(expectedRoutes));
5197 }
5198
dalyk1fcb7392018-03-05 12:42:22 -05005199 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5200 assertTrue(callbackObj instanceof LinkProperties);
5201 LinkProperties lp = (LinkProperties) callbackObj;
5202 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5203 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5204 }
5205
Hugo Benichifed512a2017-06-26 10:06:49 +09005206 private static <T> void assertEmpty(T[] ts) {
5207 int length = ts.length;
5208 assertEquals("expected empty array, but length was " + length, 0, length);
5209 }
5210
5211 private static <T> void assertLength(int expected, T[] got) {
5212 int length = got.length;
5213 assertEquals(String.format("expected array of length %s, but length was %s for %s",
5214 expected, length, Arrays.toString(got)), expected, length);
5215 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09005216
5217 private static <T> void assertException(Runnable block, Class<T> expected) {
5218 try {
5219 block.run();
5220 fail("Expected exception of type " + expected);
5221 } catch (Exception got) {
5222 if (!got.getClass().equals(expected)) {
5223 fail("Expected exception of type " + expected + " but got " + got);
5224 }
5225 return;
5226 }
5227 }
Chalard Jean0b214af2018-01-12 17:22:49 +09005228
5229 @Test
5230 public void testVpnNetworkActive() {
5231 final int uid = Process.myUid();
5232
5233 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005234 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005235 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5236 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005237 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005238 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5239 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5240 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005241 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5242 .addTransportType(TRANSPORT_WIFI).build();
5243 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005244 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005245 .addTransportType(TRANSPORT_VPN).build();
5246 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005247 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005248 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5249 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005250 mCm.registerDefaultNetworkCallback(defaultCallback);
5251 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005252
5253 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5254 mWiFiNetworkAgent.connect(false);
5255
5256 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005257 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005258 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005259 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005260 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005261 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005262
5263 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5264 final ArraySet<UidRange> ranges = new ArraySet<>();
5265 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005266 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5267 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005268 // VPN networks do not satisfy the default request and are automatically validated
5269 // by NetworkMonitor
Lorenzo Colittied3168e2019-01-23 17:54:08 +09005270 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005271 vpnNetworkAgent.setNetworkValid();
5272
Chalard Jean0b214af2018-01-12 17:22:49 +09005273 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005274 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005275 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005276
5277 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005278 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005279 wifiNetworkCallback.assertNoCallback();
5280 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005281 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5282 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005283
5284 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005285 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09005286 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005287 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5288 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005289
5290 ranges.clear();
5291 vpnNetworkAgent.setUids(ranges);
5292
5293 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005294 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005295 wifiNetworkCallback.assertNoCallback();
5296 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5297
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005298 // TODO : The default network callback should actually get a LOST call here (also see the
5299 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5300 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5301 // can't currently update their UIDs without disconnecting, so this does not matter too
5302 // much, but that is the reason the test here has to check for an update to the
5303 // capabilities instead of the expected LOST then AVAILABLE.
5304 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5305
Chalard Jean0b214af2018-01-12 17:22:49 +09005306 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005307 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005308 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005309
5310 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005311 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005312 wifiNetworkCallback.assertNoCallback();
5313 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005314 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5315 // happen outside of the test, ConnectivityService does not rematch callbacks.
5316 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005317
5318 mWiFiNetworkAgent.disconnect();
5319
5320 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005321 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005322 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5323 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005324 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005325
5326 vpnNetworkAgent.disconnect();
5327
5328 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005329 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005330 wifiNetworkCallback.assertNoCallback();
5331 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005332 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5333 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005334
5335 mCm.unregisterNetworkCallback(genericNetworkCallback);
5336 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5337 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005338 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005339 }
Chalard Jean26400492018-04-18 20:18:38 +09005340
5341 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005342 public void testVpnWithoutInternet() {
Chalard Jean26400492018-04-18 20:18:38 +09005343 final int uid = Process.myUid();
5344
5345 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5346 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005347
5348 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5349 mWiFiNetworkAgent.connect(true);
5350
5351 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5352 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5353
5354 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5355 final ArraySet<UidRange> ranges = new ArraySet<>();
5356 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005357 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5358 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005359 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005360 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005361
5362 defaultCallback.assertNoCallback();
5363 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5364
5365 vpnNetworkAgent.disconnect();
5366 defaultCallback.assertNoCallback();
5367
Varun Anand4fa80e82019-02-06 10:13:38 -08005368 mCm.unregisterNetworkCallback(defaultCallback);
5369 }
5370
5371 @Test
5372 public void testVpnWithInternet() {
5373 final int uid = Process.myUid();
5374
5375 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5376 mCm.registerDefaultNetworkCallback(defaultCallback);
5377
5378 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5379 mWiFiNetworkAgent.connect(true);
5380
5381 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5382 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5383
5384 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5385 final ArraySet<UidRange> ranges = new ArraySet<>();
5386 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005387 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5388 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005389 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005390 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005391
Chalard Jean26400492018-04-18 20:18:38 +09005392 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5393 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5394
5395 vpnNetworkAgent.disconnect();
5396 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5397 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5398
Chalard Jean26400492018-04-18 20:18:38 +09005399 mCm.unregisterNetworkCallback(defaultCallback);
5400 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005401
5402 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005403 public void testVpnUnvalidated() throws Exception {
5404 final TestNetworkCallback callback = new TestNetworkCallback();
5405 mCm.registerDefaultNetworkCallback(callback);
5406
5407 // Bring up Ethernet.
5408 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
5409 mEthernetNetworkAgent.connect(true);
5410 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5411 callback.assertNoCallback();
5412
5413 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5414 final int uid = Process.myUid();
5415 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5416 final ArraySet<UidRange> ranges = new ArraySet<>();
5417 ranges.add(new UidRange(uid, uid));
5418 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5419 mMockVpn.setUids(ranges);
5420 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
5421 mMockVpn.connect();
5422
5423 // Even though the VPN is unvalidated, it becomes the default network for our app.
5424 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5425 // TODO: this looks like a spurious callback.
5426 callback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5427 callback.assertNoCallback();
5428
5429 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5430 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5431 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5432
5433 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5434 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5435 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5436
5437 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
5438 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
5439 vpnNetworkAgent.mNetworkCapabilities));
5440
5441 // Pretend that the VPN network validates.
5442 vpnNetworkAgent.setNetworkValid();
5443 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5444 // Expect to see the validated capability, but no other changes, because the VPN is already
5445 // the default network for the app.
5446 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5447 callback.assertNoCallback();
5448
5449 vpnNetworkAgent.disconnect();
5450 callback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5451 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5452 }
5453
5454 @Test
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005455 public void testVpnSetUnderlyingNetworks() {
5456 final int uid = Process.myUid();
5457
5458 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5459 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5460 .removeCapability(NET_CAPABILITY_NOT_VPN)
5461 .addTransportType(TRANSPORT_VPN)
5462 .build();
5463 NetworkCapabilities nc;
5464 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5465 vpnNetworkCallback.assertNoCallback();
5466
5467 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5468 final ArraySet<UidRange> ranges = new ArraySet<>();
5469 ranges.add(new UidRange(uid, uid));
5470 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5471 mMockVpn.connect();
5472 mMockVpn.setUids(ranges);
5473 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5474
5475 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5476 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5477 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5478 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5479 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5480 // For safety reasons a VPN without underlying networks is considered metered.
5481 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5482
5483 // Connect cell and use it as an underlying network.
5484 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5485 mCellNetworkAgent.connect(true);
5486
5487 mService.setUnderlyingNetworksForVpn(
5488 new Network[] { mCellNetworkAgent.getNetwork() });
5489
5490 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5491 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5492 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5493 vpnNetworkAgent);
5494
5495 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5496 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5497 mWiFiNetworkAgent.connect(true);
5498
5499 mService.setUnderlyingNetworksForVpn(
5500 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5501
5502 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5503 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5504 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5505 vpnNetworkAgent);
5506
5507 // Don't disconnect, but note the VPN is not using wifi any more.
5508 mService.setUnderlyingNetworksForVpn(
5509 new Network[] { mCellNetworkAgent.getNetwork() });
5510
5511 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5512 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5513 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5514 vpnNetworkAgent);
5515
5516 // Use Wifi but not cell. Note the VPN is now unmetered.
5517 mService.setUnderlyingNetworksForVpn(
5518 new Network[] { mWiFiNetworkAgent.getNetwork() });
5519
5520 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5521 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5522 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5523 vpnNetworkAgent);
5524
5525 // Use both again.
5526 mService.setUnderlyingNetworksForVpn(
5527 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5528
5529 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5530 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5531 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5532 vpnNetworkAgent);
5533
Chalard Jean6b65ec72018-05-18 22:02:56 +09005534 // Disconnect cell. Receive update without even removing the dead network from the
5535 // underlying networks – it's dead anyway. Not metered any more.
5536 mCellNetworkAgent.disconnect();
5537 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5538 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5539 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5540 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005541
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005542 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005543 mWiFiNetworkAgent.disconnect();
5544 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5545 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005546 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09005547 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005548
5549 mMockVpn.disconnect();
5550 }
junyulai4a192e22018-06-13 15:00:37 +08005551
Mike Yuf9729752018-08-17 15:22:05 +08005552 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005553 public void testNullUnderlyingNetworks() {
5554 final int uid = Process.myUid();
5555
5556 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5557 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5558 .removeCapability(NET_CAPABILITY_NOT_VPN)
5559 .addTransportType(TRANSPORT_VPN)
5560 .build();
5561 NetworkCapabilities nc;
5562 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5563 vpnNetworkCallback.assertNoCallback();
5564
5565 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5566 final ArraySet<UidRange> ranges = new ArraySet<>();
5567 ranges.add(new UidRange(uid, uid));
5568 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5569 mMockVpn.connect();
5570 mMockVpn.setUids(ranges);
5571 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5572
5573 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5574 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5575 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5576 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5577 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5578 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5579 // In case of no default network, VPN is considered metered.
5580 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5581
5582 // Connect to Cell; Cell is the default network.
5583 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5584 mCellNetworkAgent.connect(true);
5585
5586 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5587 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5588 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5589 vpnNetworkAgent);
5590
5591 // Connect to WiFi; WiFi is the new default.
5592 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5593 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5594 mWiFiNetworkAgent.connect(true);
5595
5596 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5597 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5598 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5599 vpnNetworkAgent);
5600
5601 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5602 // the capabilities.
5603 mCellNetworkAgent.disconnect();
5604
5605 // Disconnect wifi too. Now we have no default network.
5606 mWiFiNetworkAgent.disconnect();
5607
5608 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5609 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5610 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5611 vpnNetworkAgent);
5612
5613 mMockVpn.disconnect();
5614 }
5615
5616 @Test
Varun Anandc51b06d2019-02-25 17:22:02 -08005617 public void testIsActiveNetworkMeteredOverWifi() {
5618 // Returns true by default when no network is available.
5619 assertTrue(mCm.isActiveNetworkMetered());
5620 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5621 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5622 mWiFiNetworkAgent.connect(true);
5623 waitForIdle();
5624
5625 assertFalse(mCm.isActiveNetworkMetered());
5626 }
5627
5628 @Test
5629 public void testIsActiveNetworkMeteredOverCell() {
5630 // Returns true by default when no network is available.
5631 assertTrue(mCm.isActiveNetworkMetered());
5632 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5633 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5634 mCellNetworkAgent.connect(true);
5635 waitForIdle();
5636
5637 assertTrue(mCm.isActiveNetworkMetered());
5638 }
5639
5640 @Test
5641 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
5642 // Returns true by default when no network is available.
5643 assertTrue(mCm.isActiveNetworkMetered());
5644 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5645 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5646 mCellNetworkAgent.connect(true);
5647 waitForIdle();
5648 assertTrue(mCm.isActiveNetworkMetered());
5649
5650 // Connect VPN network. By default it is using current default network (Cell).
5651 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5652 final ArraySet<UidRange> ranges = new ArraySet<>();
5653 final int uid = Process.myUid();
5654 ranges.add(new UidRange(uid, uid));
5655 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5656 mMockVpn.setUids(ranges);
5657 vpnNetworkAgent.connect(true);
5658 mMockVpn.connect();
5659 waitForIdle();
5660 // Ensure VPN is now the active network.
5661 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5662
5663 // Expect VPN to be metered.
5664 assertTrue(mCm.isActiveNetworkMetered());
5665
5666 // Connect WiFi.
5667 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5668 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5669 mWiFiNetworkAgent.connect(true);
5670 waitForIdle();
5671 // VPN should still be the active network.
5672 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5673
5674 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5675 assertFalse(mCm.isActiveNetworkMetered());
5676
5677 // Disconnecting Cell should not affect VPN's meteredness.
5678 mCellNetworkAgent.disconnect();
5679 waitForIdle();
5680
5681 assertFalse(mCm.isActiveNetworkMetered());
5682
5683 // Disconnect WiFi; Now there is no platform default network.
5684 mWiFiNetworkAgent.disconnect();
5685 waitForIdle();
5686
5687 // VPN without any underlying networks is treated as metered.
5688 assertTrue(mCm.isActiveNetworkMetered());
5689
5690 vpnNetworkAgent.disconnect();
5691 mMockVpn.disconnect();
5692 }
5693
5694 @Test
5695 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
5696 // Returns true by default when no network is available.
5697 assertTrue(mCm.isActiveNetworkMetered());
5698 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5699 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5700 mCellNetworkAgent.connect(true);
5701 waitForIdle();
5702 assertTrue(mCm.isActiveNetworkMetered());
5703
5704 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5705 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5706 mWiFiNetworkAgent.connect(true);
5707 waitForIdle();
5708 assertFalse(mCm.isActiveNetworkMetered());
5709
5710 // Connect VPN network.
5711 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5712 final ArraySet<UidRange> ranges = new ArraySet<>();
5713 final int uid = Process.myUid();
5714 ranges.add(new UidRange(uid, uid));
5715 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5716 mMockVpn.setUids(ranges);
5717 vpnNetworkAgent.connect(true);
5718 mMockVpn.connect();
5719 waitForIdle();
5720 // Ensure VPN is now the active network.
5721 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5722 // VPN is using Cell
5723 mService.setUnderlyingNetworksForVpn(
5724 new Network[] { mCellNetworkAgent.getNetwork() });
5725 waitForIdle();
5726
5727 // Expect VPN to be metered.
5728 assertTrue(mCm.isActiveNetworkMetered());
5729
5730 // VPN is now using WiFi
5731 mService.setUnderlyingNetworksForVpn(
5732 new Network[] { mWiFiNetworkAgent.getNetwork() });
5733 waitForIdle();
5734
5735 // Expect VPN to be unmetered
5736 assertFalse(mCm.isActiveNetworkMetered());
5737
5738 // VPN is using Cell | WiFi.
5739 mService.setUnderlyingNetworksForVpn(
5740 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5741 waitForIdle();
5742
5743 // Expect VPN to be metered.
5744 assertTrue(mCm.isActiveNetworkMetered());
5745
5746 // VPN is using WiFi | Cell.
5747 mService.setUnderlyingNetworksForVpn(
5748 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5749 waitForIdle();
5750
5751 // Order should not matter and VPN should still be metered.
5752 assertTrue(mCm.isActiveNetworkMetered());
5753
5754 // VPN is not using any underlying networks.
5755 mService.setUnderlyingNetworksForVpn(new Network[0]);
5756 waitForIdle();
5757
5758 // VPN without underlying networks is treated as metered.
5759 assertTrue(mCm.isActiveNetworkMetered());
5760
5761 vpnNetworkAgent.disconnect();
5762 mMockVpn.disconnect();
5763 }
5764
5765 @Test
5766 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
5767 // Returns true by default when no network is available.
5768 assertTrue(mCm.isActiveNetworkMetered());
5769 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5770 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5771 mWiFiNetworkAgent.connect(true);
5772 waitForIdle();
5773 assertFalse(mCm.isActiveNetworkMetered());
5774
5775 // Connect VPN network.
5776 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5777 final ArraySet<UidRange> ranges = new ArraySet<>();
5778 final int uid = Process.myUid();
5779 ranges.add(new UidRange(uid, uid));
5780 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5781 mMockVpn.setUids(ranges);
5782 vpnNetworkAgent.connect(true);
5783 mMockVpn.connectAsAlwaysMetered();
5784 waitForIdle();
5785 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5786
5787 // VPN is tracking current platform default (WiFi).
5788 mService.setUnderlyingNetworksForVpn(null);
5789 waitForIdle();
5790
5791 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5792 assertTrue(mCm.isActiveNetworkMetered());
5793
5794 // VPN explicitly declares WiFi as its underlying network.
5795 mService.setUnderlyingNetworksForVpn(
5796 new Network[] { mWiFiNetworkAgent.getNetwork() });
5797 waitForIdle();
5798
5799 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5800 assertTrue(mCm.isActiveNetworkMetered());
5801
5802 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5803 // anyways suppose to be metered.
5804 mWiFiNetworkAgent.disconnect();
5805 waitForIdle();
5806
5807 assertTrue(mCm.isActiveNetworkMetered());
5808
5809 vpnNetworkAgent.disconnect();
5810 }
5811
5812 @Test
Mike Yuf9729752018-08-17 15:22:05 +08005813 public void testNetworkBlockedStatus() {
5814 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5815 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5816 .addTransportType(TRANSPORT_CELLULAR)
5817 .build();
5818 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5819
5820 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5821 mCellNetworkAgent.connect(true);
5822 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5823
5824 mService.setUidRulesChanged(RULE_REJECT_ALL);
5825 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5826
5827 // ConnectivityService should cache it not to invoke the callback again.
5828 mService.setUidRulesChanged(RULE_REJECT_METERED);
5829 cellNetworkCallback.assertNoCallback();
5830
5831 mService.setUidRulesChanged(RULE_NONE);
5832 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5833
5834 mService.setUidRulesChanged(RULE_REJECT_METERED);
5835 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5836
5837 // Restrict the network based on UID rule and NOT_METERED capability change.
5838 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5839 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5840 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5841 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5842 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5843 mCellNetworkAgent);
5844 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5845 mService.setUidRulesChanged(RULE_ALLOW_METERED);
5846 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5847
5848 mService.setUidRulesChanged(RULE_NONE);
5849 cellNetworkCallback.assertNoCallback();
5850
5851 // Restrict the network based on BackgroundRestricted.
5852 mService.setRestrictBackgroundChanged(true);
5853 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5854 mService.setRestrictBackgroundChanged(true);
5855 cellNetworkCallback.assertNoCallback();
5856 mService.setRestrictBackgroundChanged(false);
5857 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5858 cellNetworkCallback.assertNoCallback();
5859
5860 mCm.unregisterNetworkCallback(cellNetworkCallback);
5861 }
5862
5863 @Test
5864 public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5865 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5866 mCm.registerDefaultNetworkCallback(defaultCallback);
5867
5868 // No Networkcallbacks invoked before any network is active.
5869 mService.setUidRulesChanged(RULE_REJECT_ALL);
5870 mService.setUidRulesChanged(RULE_NONE);
5871 mService.setUidRulesChanged(RULE_REJECT_METERED);
5872 defaultCallback.assertNoCallback();
5873
5874 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5875 mCellNetworkAgent.connect(true);
5876 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5877 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5878
5879 // Allow to use the network after switching to NOT_METERED network.
5880 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5881 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5882 mWiFiNetworkAgent.connect(true);
5883 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5884
5885 // Switch to METERED network. Restrict the use of the network.
5886 mWiFiNetworkAgent.disconnect();
5887 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5888 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5889
5890 // Network becomes NOT_METERED.
5891 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5892 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5893 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5894
5895 // Verify there's no Networkcallbacks invoked after data saver on/off.
5896 mService.setRestrictBackgroundChanged(true);
5897 mService.setRestrictBackgroundChanged(false);
5898 defaultCallback.assertNoCallback();
5899
5900 mCellNetworkAgent.disconnect();
5901 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5902 defaultCallback.assertNoCallback();
5903
5904 mCm.unregisterNetworkCallback(defaultCallback);
5905 }
5906
junyulai4a192e22018-06-13 15:00:37 +08005907 /**
5908 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5909 */
5910 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5911 InterfaceConfiguration cfg = new InterfaceConfiguration();
5912 cfg.setHardwareAddress("11:22:33:44:55:66");
5913 cfg.setLinkAddress(la);
5914 return cfg;
5915 }
5916
5917 /**
5918 * Make expected stack link properties, copied from Nat464Xlat.
5919 */
5920 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5921 LinkAddress clatAddress = la;
5922 LinkProperties stacked = new LinkProperties();
5923 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5924 RouteInfo ipv4Default = new RouteInfo(
5925 new LinkAddress(Inet4Address.ANY, 0),
5926 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5927 stacked.addRoute(ipv4Default);
5928 stacked.addLinkAddress(clatAddress);
5929 return stacked;
5930 }
5931
5932 @Test
5933 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
5934 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5935 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005936 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5937 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5938
junyulai4a192e22018-06-13 15:00:37 +08005939 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5940 .addTransportType(TRANSPORT_CELLULAR)
5941 .addCapability(NET_CAPABILITY_INTERNET)
5942 .build();
5943 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5944 mCm.registerNetworkCallback(networkRequest, networkCallback);
5945
Lorenzo Colittid593e292019-02-19 13:21:56 +09005946 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005947 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005948 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005949 final LinkProperties cellLp = new LinkProperties();
5950 cellLp.setInterfaceName(MOBILE_IFNAME);
5951 cellLp.addLinkAddress(myIpv6);
5952 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5953 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5954 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005955 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005956 reset(mMockNetd);
junyulai4a192e22018-06-13 15:00:37 +08005957 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5958 .thenReturn(getClatInterfaceConfig(myIpv4));
5959
Lorenzo Colittid593e292019-02-19 13:21:56 +09005960 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005961 mCellNetworkAgent.sendLinkProperties(cellLp);
5962 mCellNetworkAgent.connect(true);
Luke Huanga24d5d82019-04-09 18:41:49 +08005963
5964 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
5965 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
5966
junyulai4a192e22018-06-13 15:00:37 +08005967 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005968 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005969
Lorenzo Colittid593e292019-02-19 13:21:56 +09005970 // Switching default network updates TCP buffer sizes.
5971 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5972
5973 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5974 // the NAT64 prefix was removed because one was never discovered.
5975 cellLp.addLinkAddress(myIpv4);
5976 mCellNetworkAgent.sendLinkProperties(cellLp);
5977 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005978 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005979 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005980
5981 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005982 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005983 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005984 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005985
5986 // Remove IPv4 address. Expect prefix discovery to be started again.
5987 cellLp.removeLinkAddress(myIpv4);
5988 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5989 mCellNetworkAgent.sendLinkProperties(cellLp);
5990 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005991 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005992
5993 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005994 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
5995 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005996 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5997 kNat64PrefixString, 96);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005998 LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
5999 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
6000 assertEquals(0, lpBeforeClat.getStackedLinks().size());
6001 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
6002 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6003
6004 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08006005 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006006 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006007 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
6008 .getStackedLinks();
6009 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
6010
6011 // Change trivial linkproperties and see if stacked link is preserved.
6012 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
6013 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08006014 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6015
6016 List<LinkProperties> stackedLpsAfterChange =
6017 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
6018 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
6019 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
6020
Luke Huang65914772019-03-16 00:31:46 +08006021 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08006022 mResolverParamsParcelCaptor.capture());
6023 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6024 assertEquals(1, resolvrParams.servers.length);
6025 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08006026
Lorenzo Colittid593e292019-02-19 13:21:56 +09006027 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
6028 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08006029 cellLp.addLinkAddress(myIpv4);
6030 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6031 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08006032 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09006033 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08006034 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006035
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006036 // As soon as stop is called, the linkproperties lose the stacked interface.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006037 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006038 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
6039 LinkProperties expected = new LinkProperties(cellLp);
6040 expected.setNat64Prefix(kNat64Prefix);
6041 assertEquals(expected, actualLpAfterIpv4);
6042 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
6043
6044 // The interface removed callback happens but has no effect after stop is called.
6045 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6046 networkCallback.assertNoCallback();
6047
Lorenzo Colittid593e292019-02-19 13:21:56 +09006048 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006049 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006050 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006051 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006052
Lorenzo Colittid593e292019-02-19 13:21:56 +09006053 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6054 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6055 kNat64PrefixString, 96);
6056 networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
6057 mCellNetworkAgent);
6058
6059 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006060 cellLp.removeLinkAddress(myIpv4);
6061 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6062 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6063 mCellNetworkAgent.sendLinkProperties(cellLp);
6064 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006065 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006066 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6067 kNat64PrefixString, 96);
6068 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006069 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6070
Lorenzo Colittid593e292019-02-19 13:21:56 +09006071
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006072 // Clat iface comes up. Expect stacked link to be added.
6073 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006074 networkCallback.expectLinkPropertiesLike(
6075 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006076 mCellNetworkAgent);
6077
6078 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006079 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6080 kNat64PrefixString, 96);
6081 networkCallback.expectLinkPropertiesLike(
6082 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006083 mCellNetworkAgent);
6084 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6085 networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
6086 mCellNetworkAgent);
6087
6088 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08006089 mCellNetworkAgent.disconnect();
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006090 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6091 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08006092 mCm.unregisterNetworkCallback(networkCallback);
6093 }
Chiachang Wanga6093042018-09-28 22:42:48 +08006094
6095 @Test
6096 public void testDataActivityTracking() throws RemoteException {
6097 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6098 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6099 .addCapability(NET_CAPABILITY_INTERNET)
6100 .build();
6101 mCm.registerNetworkCallback(networkRequest, networkCallback);
6102
6103 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6104 final LinkProperties cellLp = new LinkProperties();
6105 cellLp.setInterfaceName(MOBILE_IFNAME);
6106 mCellNetworkAgent.sendLinkProperties(cellLp);
6107 reset(mNetworkManagementService);
6108 mCellNetworkAgent.connect(true);
6109 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6110 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6111 eq(ConnectivityManager.TYPE_MOBILE));
6112
6113 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6114 final LinkProperties wifiLp = new LinkProperties();
6115 wifiLp.setInterfaceName(WIFI_IFNAME);
6116 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6117
6118 // Network switch
6119 reset(mNetworkManagementService);
6120 mWiFiNetworkAgent.connect(true);
6121 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6122 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6123 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6124 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6125 eq(ConnectivityManager.TYPE_WIFI));
6126 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6127
6128 // Disconnect wifi and switch back to cell
6129 reset(mNetworkManagementService);
6130 mWiFiNetworkAgent.disconnect();
6131 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
6132 assertNoCallbacks(networkCallback);
6133 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6134 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6135 eq(ConnectivityManager.TYPE_MOBILE));
6136
6137 // reconnect wifi
6138 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6139 wifiLp.setInterfaceName(WIFI_IFNAME);
6140 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6141 mWiFiNetworkAgent.connect(true);
6142 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6143 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6144 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6145
6146 // Disconnect cell
6147 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006148 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006149 mCellNetworkAgent.disconnect();
6150 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6151 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6152 // sent as network being switched. Ensure rule removal for cell will not be triggered
6153 // unexpectedly before network being removed.
6154 waitForIdle();
6155 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006156 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6157 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08006158 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006159
6160 // Disconnect wifi
6161 ConditionVariable cv = waitForConnectivityBroadcasts(1);
6162 reset(mNetworkManagementService);
6163 mWiFiNetworkAgent.disconnect();
6164 waitFor(cv);
6165 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6166
6167 // Clean up
6168 mCm.unregisterNetworkCallback(networkCallback);
6169 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006170
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006171 private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006172 String[] values = tcpBufferSizes.split(",");
6173 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6174 String wmemValues = String.join(" ", values[3], values[4], values[5]);
6175 waitForIdle();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006176 try {
6177 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
6178 } catch (RemoteException e) {
6179 fail("mMockNetd should never throw RemoteException");
6180 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006181 reset(mMockNetd);
6182 }
6183
6184 @Test
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006185 public void testTcpBufferReset() {
6186 final String testTcpBufferSizes = "1,2,3,4,5,6";
6187
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006188 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6189 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006190 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006191 mCellNetworkAgent.connect(false);
6192 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6193
6194 // Change link Properties should have updated tcp buffer size.
6195 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006196 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006197 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006198 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006199 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006200
6201 @Test
6202 public void testGetGlobalProxyForNetwork() {
6203 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6204 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6205 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6206 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6207 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6208 }
6209
6210 @Test
6211 public void testGetProxyForActiveNetwork() {
6212 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6213 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6214 mWiFiNetworkAgent.connect(true);
6215 waitForIdle();
6216 assertNull(mService.getProxyForNetwork(null));
6217
6218 final LinkProperties testLinkProperties = new LinkProperties();
6219 testLinkProperties.setHttpProxy(testProxyInfo);
6220
6221 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6222 waitForIdle();
6223
6224 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6225 }
6226
6227 @Test
6228 public void testGetProxyForVPN() {
6229 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6230
6231 // Set up a WiFi network with no proxy
6232 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6233 mWiFiNetworkAgent.connect(true);
6234 waitForIdle();
6235 assertNull(mService.getProxyForNetwork(null));
6236
6237 // Set up a VPN network with a proxy
6238 final int uid = Process.myUid();
6239 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
6240 final ArraySet<UidRange> ranges = new ArraySet<>();
6241 ranges.add(new UidRange(uid, uid));
6242 mMockVpn.setUids(ranges);
6243 LinkProperties testLinkProperties = new LinkProperties();
6244 testLinkProperties.setHttpProxy(testProxyInfo);
6245 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6246 waitForIdle();
6247
6248 // Connect to VPN with proxy
6249 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6250 vpnNetworkAgent.connect(true);
6251 mMockVpn.connect();
6252 waitForIdle();
6253
6254 // Test that the VPN network returns a proxy, and the WiFi does not.
6255 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6256 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6257 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6258
6259 // Test that the VPN network returns no proxy when it is set to null.
6260 testLinkProperties.setHttpProxy(null);
6261 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6262 waitForIdle();
6263 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6264 assertNull(mService.getProxyForNetwork(null));
6265
6266 // Set WiFi proxy and check that the vpn proxy is still null.
6267 testLinkProperties.setHttpProxy(testProxyInfo);
6268 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6269 waitForIdle();
6270 assertNull(mService.getProxyForNetwork(null));
6271
6272 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6273 // correct proxy setting.
6274 vpnNetworkAgent.disconnect();
6275 waitForIdle();
6276 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6277 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6278 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6279 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006280
6281 @Test
6282 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6283 LinkProperties lp = new LinkProperties();
6284 lp.setInterfaceName("tun0");
6285 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6286 // The uid range needs to cover the test app so the network is visible to it.
6287 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6288 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6289
6290 // Connected VPN should have interface rules set up. There are two expected invocations,
6291 // one during VPN uid update, one during VPN LinkProperties update
6292 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6293 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6294 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6295 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6296 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6297
6298 vpnNetworkAgent.disconnect();
6299 waitForIdle();
6300
6301 // Disconnected VPN should have interface rules removed
6302 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6303 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6304 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6305 }
6306
6307 @Test
6308 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6309 LinkProperties lp = new LinkProperties();
6310 lp.setInterfaceName("tun0");
6311 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6312 // The uid range needs to cover the test app so the network is visible to it.
6313 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6314 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6315
6316 // Legacy VPN should not have interface rules set up
6317 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6318 }
6319
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09006320 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006321 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6322 throws Exception {
6323 LinkProperties lp = new LinkProperties();
6324 lp.setInterfaceName("tun0");
6325 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6326 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6327 // The uid range needs to cover the test app so the network is visible to it.
6328 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6329 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6330
6331 // IPv6 unreachable route should not be misinterpreted as a default route
6332 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6333 }
6334
6335 @Test
6336 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6337 LinkProperties lp = new LinkProperties();
6338 lp.setInterfaceName("tun0");
6339 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6340 // The uid range needs to cover the test app so the network is visible to it.
6341 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6342 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6343
6344 // Connected VPN should have interface rules set up. There are two expected invocations,
6345 // one during VPN uid update, one during VPN LinkProperties update
6346 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6347 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6348 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6349 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6350
6351 reset(mMockNetd);
6352 InOrder inOrder = inOrder(mMockNetd);
6353 lp.setInterfaceName("tun1");
6354 vpnNetworkAgent.sendLinkProperties(lp);
6355 waitForIdle();
6356 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6357 // removed first, then new rules added)
6358 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6359 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6360 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6361 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6362
6363 reset(mMockNetd);
6364 lp = new LinkProperties();
6365 lp.setInterfaceName("tun1");
6366 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6367 vpnNetworkAgent.sendLinkProperties(lp);
6368 waitForIdle();
6369 // VPN not routing everything should no longer have interface filtering rules
6370 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6371 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6372
6373 reset(mMockNetd);
6374 lp = new LinkProperties();
6375 lp.setInterfaceName("tun1");
6376 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6377 vpnNetworkAgent.sendLinkProperties(lp);
6378 waitForIdle();
6379 // Back to routing all IPv6 traffic should have filtering rules
6380 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6381 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6382 }
6383
6384 @Test
6385 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6386 LinkProperties lp = new LinkProperties();
6387 lp.setInterfaceName("tun0");
6388 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6389 // The uid range needs to cover the test app so the network is visible to it.
6390 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
6391 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID,
6392 Collections.singleton(vpnRange));
6393
6394 reset(mMockNetd);
6395 InOrder inOrder = inOrder(mMockNetd);
6396
6397 // Update to new range which is old range minus APP1, i.e. only APP2
6398 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6399 new UidRange(vpnRange.start, APP1_UID - 1),
6400 new UidRange(APP1_UID + 1, vpnRange.stop)));
6401 vpnNetworkAgent.setUids(newRanges);
6402 waitForIdle();
6403
6404 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6405 // Verify old rules are removed before new rules are added
6406 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6407 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6408 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6409 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6410 }
6411
6412
6413 private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
6414 Set<UidRange> vpnRange) {
6415 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
6416 vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
6417 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6418 mMockVpn.connect();
6419 mMockVpn.setUids(vpnRange);
6420 vpnNetworkAgent.connect(true);
6421 waitForIdle();
6422 return vpnNetworkAgent;
6423 }
6424
6425 private void assertContainsExactly(int[] actual, int... expected) {
6426 int[] sortedActual = Arrays.copyOf(actual, actual.length);
6427 int[] sortedExpected = Arrays.copyOf(expected, expected.length);
6428 Arrays.sort(sortedActual);
6429 Arrays.sort(sortedExpected);
6430 assertArrayEquals(sortedExpected, sortedActual);
6431 }
6432
6433 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6434 final PackageInfo packageInfo = new PackageInfo();
6435 packageInfo.requestedPermissions = new String[0];
6436 packageInfo.applicationInfo = new ApplicationInfo();
6437 packageInfo.applicationInfo.privateFlags = 0;
6438 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6439 UserHandle.getAppId(uid));
6440 return packageInfo;
6441 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006442}