blob: 3c5bb6a0c64fabfd89c71b15815bbd366e2e5082 [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;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070031import static android.net.ConnectivityManager.TYPE_WIFI;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090032import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
lucasline252a742019-03-12 13:08:03 +080033import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090034import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060035import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
36import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
38import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
44import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
45import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
46import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090047import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060048import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080049import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060050import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
52import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
53import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
54import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
55import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
56import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
57import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090058import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060059import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
60import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080061import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
62import static android.net.NetworkPolicyManager.RULE_NONE;
63import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
64import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000065import static android.net.RouteInfo.RTN_UNREACHABLE;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060066
67import static com.android.internal.util.TestUtils.waitForIdleHandler;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090068import static com.android.internal.util.TestUtils.waitForIdleLooper;
junyulai7c469172019-01-16 20:23:34 +080069import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090070
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000071import static org.junit.Assert.assertArrayEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090072import static org.junit.Assert.assertEquals;
73import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080074import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090075import static org.junit.Assert.assertNotNull;
76import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060077import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090078import static org.junit.Assert.fail;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000079import static org.mockito.ArgumentMatchers.eq;
Erik Klinee89953b2018-01-11 16:11:10 +090080import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +090081import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060082import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090083import static org.mockito.Mockito.doAnswer;
84import static org.mockito.Mockito.doNothing;
Erik Kline117e7f32018-03-04 21:01:01 +090085import static org.mockito.Mockito.eq;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000086import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080087import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060088import static org.mockito.Mockito.never;
89import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090090import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090091import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +090092import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060093import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -070094import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090095import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070096
junyulai7c469172019-01-16 20:23:34 +080097import android.annotation.NonNull;
Lorenzo Colitti73b209382016-09-15 22:18:09 +090098import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040099import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400100import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900101import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900102import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700103import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400104import android.content.Intent;
105import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000106import android.content.pm.ApplicationInfo;
107import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100108import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000109import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900110import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400111import android.net.ConnectivityManager;
112import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900113import android.net.ConnectivityManager.PacketKeepalive;
114import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900115import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900116import android.net.ConnectivityThread;
Luke Huang65914772019-03-16 00:31:46 +0800117import android.net.IDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800118import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900119import android.net.INetworkMonitor;
120import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800121import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700122import android.net.INetworkPolicyManager;
123import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800124import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900125import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800126import android.net.IpSecManager;
127import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900128import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700129import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700130import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400131import android.net.Network;
132import android.net.NetworkAgent;
133import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700134import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700135import android.net.NetworkInfo;
136import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400137import android.net.NetworkMisc;
138import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700139import android.net.NetworkSpecifier;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900140import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800141import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100142import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000143import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800144import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700145import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800146import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900147import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900148import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900149import android.net.shared.NetworkMonitorUtils;
150import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900151import android.net.util.MultinetworkPolicyTracker;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100152import android.os.Binder;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400153import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700154import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700155import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700156import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900157import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900158import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700159import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800160import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700161import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000162import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800163import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900164import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900165import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000166import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900167import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800168import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900169import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800170import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100171import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700172import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800173import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700174
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800175import androidx.test.InstrumentationRegistry;
176import androidx.test.filters.SmallTest;
177import androidx.test.runner.AndroidJUnit4;
178
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900179import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800180import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900181import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900182import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900183import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900184import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900185import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900186import com.android.server.connectivity.DefaultNetworkMetrics;
187import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900188import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800189import com.android.server.connectivity.Nat464Xlat;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000190import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800191import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900192import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900193import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900194import com.android.server.net.NetworkPolicyManagerInternal;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400195
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900196import org.junit.After;
197import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900198import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900199import org.junit.Test;
200import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900201import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000202import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900203import org.mockito.Mock;
204import org.mockito.MockitoAnnotations;
205import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900206import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900207
junyulai0c666972019-03-04 22:45:36 +0800208import java.io.IOException;
209import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800210import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000211import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700212import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900213import java.net.InetSocketAddress;
214import java.net.Socket;
junyulai4a192e22018-06-13 15:00:37 +0800215import java.net.UnknownHostException;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400216import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900217import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100218import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800219import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500220import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100221import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900222import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100223import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900224import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800225import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800226import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800227import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900228import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900229import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700230import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900231import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700232
233/**
234 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400235 *
236 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900237 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700238 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900239@RunWith(AndroidJUnit4.class)
240@SmallTest
241public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700242 private static final String TAG = "ConnectivityServiceTest";
243
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900244 private static final int TIMEOUT_MS = 500;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900245 private static final int TEST_LINGER_DELAY_MS = 250;
246 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
247 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
248 // timeout. For this, our assertions should run fast enough to leave less than
249 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
250 // supposedly fired, and the time we call expectCallback.
251 private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900252 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
253 // complete before callbacks are verified.
254 private final static int TEST_REQUEST_TIMEOUT_MS = 150;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900255
junyulai4a192e22018-06-13 15:00:37 +0800256 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700257 private static final String MOBILE_IFNAME = "test_rmnet_data0";
258 private static final String WIFI_IFNAME = "test_wlan0";
Luke Huang65914772019-03-16 00:31:46 +0800259 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700260
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900261 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400262 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900263 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400264 private MockNetworkAgent mWiFiNetworkAgent;
265 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900266 private MockNetworkAgent mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900267 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900268 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800269 private INetworkPolicyListener mPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700270
Hugo Benichi64901e52017-10-19 14:42:40 +0900271 @Mock IpConnectivityMetrics.Logger mMetricsService;
272 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900273 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600274 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800275 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800276 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800277 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900278 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100279 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000280 @Mock UserManager mUserManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900281
waynema13516842019-03-12 18:13:49 +0800282 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
283 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900284
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900285 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
286 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
287 // reflect the state of our test ConnectivityService.
288 private class WrappedConnectivityManager extends ConnectivityManager {
289 private Network mFakeBoundNetwork;
290
291 public synchronized boolean bindProcessToNetwork(Network network) {
292 mFakeBoundNetwork = network;
293 return true;
294 }
295
296 public synchronized Network getBoundNetworkForProcess() {
297 return mFakeBoundNetwork;
298 }
299
300 public WrappedConnectivityManager(Context context, ConnectivityService service) {
301 super(context, service);
302 }
303 }
304
Paul Jensend7b6ca92015-05-13 14:05:12 -0400305 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900306 private final MockContentResolver mContentResolver;
307
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900308 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900309 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900310
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900311 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400312 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900313
314 mResources = spy(base.getResources());
315 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
316 thenReturn(new String[] {
317 "wifi,1,1,1,-1,true",
318 "mobile,0,0,0,-1,true",
319 "mobile_mms,2,0,2,60000,true",
320 });
321
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900322 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900323 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400324 }
325
326 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900327 public void startActivityAsUser(Intent intent, UserHandle handle) {
328 mStartedActivities.offer(intent);
329 }
330
331 public Intent expectStartActivityIntent(int timeoutMs) {
332 Intent intent = null;
333 try {
334 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
335 } catch (InterruptedException e) {}
336 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
337 return intent;
338 }
339
340 public void expectNoStartActivityIntent(int timeoutMs) {
341 try {
342 assertNull("Received unexpected Intent to start activity",
343 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
344 } catch (InterruptedException e) {}
345 }
346
347 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900348 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900349 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
350 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900351 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000352 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400353 return super.getSystemService(name);
354 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900355
356 @Override
357 public ContentResolver getContentResolver() {
358 return mContentResolver;
359 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900360
361 @Override
362 public Resources getResources() {
363 return mResources;
364 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100365
366 @Override
367 public PackageManager getPackageManager() {
368 return mPackageManager;
369 }
370 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400371
Hugo Benichi669f0232017-06-29 22:58:39 +0900372 public void waitForIdle(int timeoutMsAsInt) {
373 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900374 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
375 waitForIdle(mCellNetworkAgent, timeoutMs);
376 waitForIdle(mWiFiNetworkAgent, timeoutMs);
377 waitForIdle(mEthernetNetworkAgent, timeoutMs);
378 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900379 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900380 }
381
Hugo Benichi669f0232017-06-29 22:58:39 +0900382 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900383 if (agent == null) {
384 return;
385 }
386 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
387 }
388
389 private void waitForIdle() {
390 waitForIdle(TIMEOUT_MS);
391 }
392
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900393 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900394 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900395 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
396
397 // Tests that waitForIdle returns immediately if the service is already idle.
398 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900399 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900400 }
401
402 // Bring up a network that we can use to send messages to ConnectivityService.
403 ConditionVariable cv = waitForConnectivityBroadcasts(1);
404 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
405 mWiFiNetworkAgent.connect(false);
406 waitFor(cv);
407 Network n = mWiFiNetworkAgent.getNetwork();
408 assertNotNull(n);
409
410 // Tests that calling waitForIdle waits for messages to be processed.
411 for (int i = 0; i < attempts; i++) {
412 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900413 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900414 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
415 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900416 }
417
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900418 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
419 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800420 @Ignore
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900421 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900422 // Bring up a network that we can use to send messages to ConnectivityService.
423 ConditionVariable cv = waitForConnectivityBroadcasts(1);
424 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
425 mWiFiNetworkAgent.connect(false);
426 waitFor(cv);
427 Network n = mWiFiNetworkAgent.getNetwork();
428 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900429
430 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900431 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900432 for (int i = 0; i < attempts; i++) {
433 mWiFiNetworkAgent.setSignalStrength(i);
434 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
435 // We hit a race condition, as expected. Pass the test.
436 return;
437 }
438 }
439
440 // No race? There is a bug in this test.
441 fail("expected race condition at least once in " + attempts + " attempts");
442 }
443
Paul Jensend7b6ca92015-05-13 14:05:12 -0400444 private class MockNetworkAgent {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900445 private final INetworkMonitor mNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400446 private final NetworkInfo mNetworkInfo;
447 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900448 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400449 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400450 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700451 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400452 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400453 private NetworkAgent mNetworkAgent;
junyulai0c666972019-03-04 22:45:36 +0800454 private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
junyulai48eac1d42018-12-27 17:25:29 +0800455 private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900456 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400457 // Contains the redirectUrl from networkStatus(). Before reading, wait for
458 // mNetworkStatusReceived.
459 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400460
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900461 private INetworkMonitorCallbacks mNmCallbacks;
462 private int mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
463 private String mNmValidationRedirectUrl = null;
464 private boolean mNmProvNotificationRequested = false;
465
466 void setNetworkValid() {
467 mNmValidationResult = NETWORK_TEST_RESULT_VALID;
468 mNmValidationRedirectUrl = null;
469 }
470
471 void setNetworkInvalid() {
472 mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
473 mNmValidationRedirectUrl = null;
474 }
475
476 void setNetworkPortal(String redirectUrl) {
477 setNetworkInvalid();
478 mNmValidationRedirectUrl = redirectUrl;
479 }
480
lucasline252a742019-03-12 13:08:03 +0800481 void setNetworkPartial() {
482 mNmValidationResult = NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
483 mNmValidationRedirectUrl = null;
484 }
485
Paul Jensend7b6ca92015-05-13 14:05:12 -0400486 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100487 this(transport, new LinkProperties());
488 }
489
490 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400491 final int type = transportToLegacyType(transport);
Chalard Jean0b214af2018-01-12 17:22:49 +0900492 final String typeName = ConnectivityManager.getNetworkTypeName(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400493 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
494 mNetworkCapabilities = new NetworkCapabilities();
495 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400496 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900497 case TRANSPORT_ETHERNET:
498 mScore = 70;
499 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400500 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400501 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400502 break;
503 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400504 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400505 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900506 case TRANSPORT_WIFI_AWARE:
507 mScore = 20;
508 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900509 case TRANSPORT_VPN:
Chalard Jeanb552c462018-02-21 18:43:54 +0900510 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
Chalard Jeandda156a2018-01-10 21:19:32 +0900511 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
Chalard Jean0b214af2018-01-12 17:22:49 +0900512 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400513 default:
514 throw new UnsupportedOperationException("unimplemented network type");
515 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900516 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900517 mHandlerThread.start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900518
519 mNetworkMonitor = mock(INetworkMonitor.class);
520 final Answer validateAnswer = inv -> {
521 new Thread(this::onValidationRequested).start();
522 return null;
523 };
524
525 try {
Remi NGUYEN VAN3962f672019-03-27 15:42:53 +0900526 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900527 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
528 } catch (RemoteException e) {
529 fail(e.getMessage());
530 }
531
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900532 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900533 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
534 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
535 doNothing().when(mNetworkStack).makeNetworkMonitor(
536 nmNetworkCaptor.capture(),
537 any() /* name */,
538 nmCbCaptor.capture());
539
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900540 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
541 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Chalard Jean05ab6812018-05-02 21:14:54 +0900542 linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900543 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900544 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900545
546 @Override
junyulai06835112019-01-03 18:50:15 +0800547 public void startSocketKeepalive(Message msg) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900548 int slot = msg.arg1;
549 if (mExpectedKeepaliveSlot != null) {
550 assertEquals((int) mExpectedKeepaliveSlot, slot);
551 }
junyulai06835112019-01-03 18:50:15 +0800552 onSocketKeepaliveEvent(slot, mStartKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900553 }
554
555 @Override
junyulai06835112019-01-03 18:50:15 +0800556 public void stopSocketKeepalive(Message msg) {
557 onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900558 }
Paul Jensen232437312016-04-06 09:51:26 -0400559
560 @Override
561 public void networkStatus(int status, String redirectUrl) {
562 mRedirectUrl = redirectUrl;
563 mNetworkStatusReceived.open();
564 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700565
566 @Override
567 protected void preventAutomaticReconnect() {
568 mPreventReconnectReceived.open();
569 }
Aaron Huang9eeaa3a2019-04-19 22:47:26 +0800570
571 @Override
572 protected void addKeepalivePacketFilter(Message msg) {
573 Log.i(TAG, "Add keepalive packet filter.");
574 }
575
576 @Override
577 protected void removeKeepalivePacketFilter(Message msg) {
578 Log.i(TAG, "Remove keepalive packet filter.");
579 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400580 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900581
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900582 assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900583 mNmCallbacks = nmCbCaptor.getValue();
584
585 try {
586 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
587 } catch (RemoteException e) {
588 fail(e.getMessage());
589 }
590
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900591 // Waits for the NetworkAgent to be registered, which includes the creation of the
592 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900593 waitForIdle();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900594 }
595
596 private void onValidationRequested() {
597 try {
598 if (mNmProvNotificationRequested
599 && mNmValidationResult == NETWORK_TEST_RESULT_VALID) {
600 mNmCallbacks.hideProvisioningNotification();
601 mNmProvNotificationRequested = false;
602 }
603
604 mNmCallbacks.notifyNetworkTested(
605 mNmValidationResult, mNmValidationRedirectUrl);
606
607 if (mNmValidationRedirectUrl != null) {
608 mNmCallbacks.showProvisioningNotification(
Remi NGUYEN VAN9c5d9642019-02-07 21:29:57 +0900609 "test_provisioning_notif_action", "com.android.test.package");
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900610 mNmProvNotificationRequested = true;
611 }
612 } catch (RemoteException e) {
613 fail(e.getMessage());
614 }
Paul Jensen3d911462015-06-12 06:40:24 -0400615 }
616
617 public void adjustScore(int change) {
618 mScore += change;
619 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400620 }
621
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900622 public void explicitlySelected(boolean acceptUnvalidated) {
623 mNetworkAgent.explicitlySelected(acceptUnvalidated);
624 }
625
Paul Jensen85cf78e2015-06-25 13:25:07 -0400626 public void addCapability(int capability) {
627 mNetworkCapabilities.addCapability(capability);
628 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
629 }
630
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900631 public void removeCapability(int capability) {
632 mNetworkCapabilities.removeCapability(capability);
633 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
634 }
635
Chalard Jean0b214af2018-01-12 17:22:49 +0900636 public void setUids(Set<UidRange> uids) {
637 mNetworkCapabilities.setUids(uids);
638 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
639 }
640
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900641 public void setSignalStrength(int signalStrength) {
642 mNetworkCapabilities.setSignalStrength(signalStrength);
643 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
644 }
645
Etan Cohena7434272017-04-03 12:17:51 -0700646 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
647 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900648 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
649 }
650
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900651 public void setNetworkCapabilities(NetworkCapabilities nc,
652 boolean sendToConnectivityService) {
653 mNetworkCapabilities.set(nc);
654 if (sendToConnectivityService) {
655 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
656 }
657 }
658
Paul Jensene0988542015-06-25 15:30:08 -0400659 public void connectWithoutInternet() {
660 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
661 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
662 }
663
Paul Jensend7b6ca92015-05-13 14:05:12 -0400664 /**
Paul Jensene0988542015-06-25 15:30:08 -0400665 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400666 * @param validated Indicate if network should pretend to be validated.
667 */
668 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900669 connect(validated, true);
670 }
671
672 /**
673 * Transition this NetworkAgent to CONNECTED state.
674 * @param validated Indicate if network should pretend to be validated.
675 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
676 */
677 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900678 assertEquals("MockNetworkAgents can only be connected once",
679 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400680 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
681
Paul Jensend7b6ca92015-05-13 14:05:12 -0400682 NetworkCallback callback = null;
683 final ConditionVariable validatedCv = new ConditionVariable();
684 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900685 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400686 NetworkRequest request = new NetworkRequest.Builder()
687 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900688 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400689 .build();
690 callback = new NetworkCallback() {
691 public void onCapabilitiesChanged(Network network,
692 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400693 if (network.equals(getNetwork()) &&
694 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400695 validatedCv.open();
696 }
697 }
698 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400699 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400700 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900701 if (hasInternet) {
702 addCapability(NET_CAPABILITY_INTERNET);
703 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400704
Paul Jensene0988542015-06-25 15:30:08 -0400705 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400706
707 if (validated) {
708 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400709 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900710 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400711 }
712
713 if (callback != null) mCm.unregisterNetworkCallback(callback);
714 }
715
Paul Jensen232437312016-04-06 09:51:26 -0400716 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900717 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400718 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400719 }
720
lucasline252a742019-03-12 13:08:03 +0800721 public void connectWithPartialConnectivity() {
722 setNetworkPartial();
723 connect(false);
724 }
725
Erik Kline1d3db322017-02-28 16:20:20 +0900726 public void suspend() {
727 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
728 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
729 }
730
Chalard Jean804b8fb2018-01-30 22:41:41 +0900731 public void resume() {
732 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
733 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
734 }
735
Paul Jensend7b6ca92015-05-13 14:05:12 -0400736 public void disconnect() {
737 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
738 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
739 }
740
741 public Network getNetwork() {
742 return new Network(mNetworkAgent.netId);
743 }
Paul Jensene0988542015-06-25 15:30:08 -0400744
Calvin On1f64f3f2016-10-11 15:10:46 -0700745 public ConditionVariable getPreventReconnectReceived() {
746 return mPreventReconnectReceived;
747 }
748
Paul Jensene0988542015-06-25 15:30:08 -0400749 public ConditionVariable getDisconnectedCV() {
750 return mDisconnected;
751 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400752
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900753 public void sendLinkProperties(LinkProperties lp) {
754 mNetworkAgent.sendLinkProperties(lp);
755 }
756
757 public void setStartKeepaliveError(int error) {
758 mStartKeepaliveError = error;
759 }
760
761 public void setStopKeepaliveError(int error) {
762 mStopKeepaliveError = error;
763 }
764
765 public void setExpectedKeepaliveSlot(Integer slot) {
766 mExpectedKeepaliveSlot = slot;
767 }
Paul Jensen232437312016-04-06 09:51:26 -0400768
769 public String waitForRedirectUrl() {
770 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
771 return mRedirectUrl;
772 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900773
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900774 public NetworkAgent getNetworkAgent() {
775 return mNetworkAgent;
776 }
777
Chalard Jean804b8fb2018-01-30 22:41:41 +0900778 public NetworkCapabilities getNetworkCapabilities() {
779 return mNetworkCapabilities;
780 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400781 }
782
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900783 /**
784 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
785 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900786 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900787 * expectRemoveRequests.
788 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700789 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400790 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
791 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400792 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700793
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900794 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900795 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
796 // once, then cause some other thread to add or remove requests, then call
797 // waitForRequests().
798 // It is not possible to wait for both add and remove requests. When adding, the queue
799 // contains the expected score. When removing, the value is unused, all matters is the
800 // number of objects in the queue.
801 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900802
803 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900804 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900805 private boolean mExpectingAdditions;
806
Etan Cohenddb720a2019-01-08 12:09:18 -0800807 // Used to collect the networks requests managed by this factory. This is a duplicate of
808 // the internal information stored in the NetworkFactory (which is private).
809 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
810
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700811 public MockNetworkFactory(Looper looper, Context context, String logTag,
812 NetworkCapabilities filter) {
813 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900814 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700815 }
816
817 public int getMyRequestCount() {
818 return getRequestCount();
819 }
820
821 protected void startNetwork() {
822 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400823 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700824 }
825
826 protected void stopNetwork() {
827 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400828 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700829 }
830
831 public boolean getMyStartRequested() {
832 return mNetworkStarted.get();
833 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400834
835 public ConditionVariable getNetworkStartedCV() {
836 mNetworkStartedCV.close();
837 return mNetworkStartedCV;
838 }
839
840 public ConditionVariable getNetworkStoppedCV() {
841 mNetworkStoppedCV.close();
842 return mNetworkStoppedCV;
843 }
844
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900845 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900846 protected void handleAddRequest(NetworkRequest request, int score,
847 int factorySerialNumber) {
848 synchronized (mExpectations) {
849 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900850
Chalard Jean05ab6812018-05-02 21:14:54 +0900851 assertNotNull("Added more requests than expected (" + request + " score : "
852 + score + ")", expectedScore);
853 // If we're expecting anything, we must be expecting additions.
854 if (!mExpectingAdditions) {
855 fail("Can't add requests while expecting requests to be removed");
856 }
857 if (expectedScore != score) {
858 fail("Expected score was " + expectedScore + " but actual was " + score
859 + " in added request");
860 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900861
Chalard Jean05ab6812018-05-02 21:14:54 +0900862 // Add the request.
863 mNetworkRequests.put(request.requestId, request);
864 super.handleAddRequest(request, score, factorySerialNumber);
865 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900866 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400867 }
868
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900869 @Override
870 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900871 synchronized (mExpectations) {
872 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900873
Chalard Jean05ab6812018-05-02 21:14:54 +0900874 assertTrue("Removed more requests than expected", expectedScore != null);
875 // If we're expecting anything, we must be expecting removals.
876 if (mExpectingAdditions) {
877 fail("Can't remove requests while expecting requests to be added");
878 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900879
Chalard Jean05ab6812018-05-02 21:14:54 +0900880 // Remove the request.
881 mNetworkRequests.remove(request.requestId);
882 super.handleRemoveRequest(request);
883 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900884 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400885 }
886
Etan Cohenddb720a2019-01-08 12:09:18 -0800887 // Trigger releasing the request as unfulfillable
888 public void triggerUnfulfillable(NetworkRequest r) {
889 super.releaseRequestAsUnfulfillableByAnyFactory(r);
890 }
891
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900892 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900893 if (mExpectations.size() != 0) {
894 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900895 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400896 }
897
Chalard Jean05ab6812018-05-02 21:14:54 +0900898 // Expects that requests with the specified scores will be added.
899 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900900 assertNoExpectations();
901 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900902 for (int score : scores) {
903 mExpectations.add(score);
904 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400905 }
906
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900907 // Expects that count requests will be removed.
908 public void expectRemoveRequests(final int count) {
909 assertNoExpectations();
910 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900911 for (int i = 0; i < count; ++i) {
912 mExpectations.add(0); // For removals the score is ignored so any value will do.
913 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900914 }
915
916 // Waits for the expected request additions or removals to happen within a timeout.
917 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900918 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
919 synchronized (mExpectations) {
920 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
921 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
922 }
923 }
924 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900925 final String msg = count + " requests still not " +
926 (mExpectingAdditions ? "added" : "removed") +
927 " after " + TIMEOUT_MS + " ms";
928 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900929 }
930
Etan Cohenddb720a2019-01-08 12:09:18 -0800931 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
932 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900933 waitForRequests();
934 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800935 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400936 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700937 }
938
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900939 private static Looper startHandlerThreadAndReturnLooper() {
940 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
941 handlerThread.start();
942 return handlerThread.getLooper();
943 }
944
945 private class MockVpn extends Vpn {
946 // TODO : the interactions between this mock and the mock network agent are too
947 // hard to get right at this moment, because it's unclear in which case which
948 // target needs to get a method call or both, and in what order. It's because
949 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
950 // parent class of MockVpn agent wants that responsibility.
951 // That being said inside the test it should be possible to make the interactions
952 // harder to get wrong with precise speccing, judicious comments, helper methods
953 // and a few sprinkled assertions.
954
955 private boolean mConnected = false;
956 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
957 // not inherit from NetworkAgent.
958 private MockNetworkAgent mMockNetworkAgent;
959
960 public MockVpn(int userId) {
961 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
962 userId);
963 }
964
965 public void setNetworkAgent(MockNetworkAgent agent) {
966 waitForIdle(agent, TIMEOUT_MS);
967 mMockNetworkAgent = agent;
968 mNetworkAgent = agent.getNetworkAgent();
969 mNetworkCapabilities.set(agent.getNetworkCapabilities());
970 }
971
972 public void setUids(Set<UidRange> uids) {
973 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800974 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900975 }
976
977 @Override
978 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800979 if (mMockNetworkAgent == null) {
980 return NETID_UNSET;
981 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900982 return mMockNetworkAgent.getNetwork().netId;
983 }
984
985 @Override
986 public boolean appliesToUid(int uid) {
987 return mConnected; // Trickery to simplify testing.
988 }
989
990 @Override
991 protected boolean isCallerEstablishedOwnerLocked() {
992 return mConnected; // Similar trickery
993 }
994
Varun Anandc51b06d2019-02-25 17:22:02 -0800995 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900996 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
997 mConnected = true;
998 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -0800999 mConfig.isMetered = isAlwaysMetered;
1000 }
1001
1002 public void connectAsAlwaysMetered() {
1003 connect(true /* isAlwaysMetered */);
1004 }
1005
1006 public void connect() {
1007 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001008 }
1009
1010 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001011 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1012 if (!mConnected) return null;
1013 super.updateCapabilities(defaultNetwork);
1014 // Because super.updateCapabilities will update the capabilities of the agent but
1015 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001016 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -08001017 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001018 }
1019
1020 private void copyCapabilitiesToNetworkAgent() {
1021 if (null != mMockNetworkAgent) {
1022 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1023 false /* sendToConnectivityService */);
1024 }
1025 }
1026
1027 public void disconnect() {
1028 mConnected = false;
1029 mConfig = null;
1030 }
1031 }
1032
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001033 private class FakeWakeupMessage extends WakeupMessage {
1034 private static final int UNREASONABLY_LONG_WAIT = 1000;
1035
1036 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
1037 super(context, handler, cmdName, cmd);
1038 }
1039
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001040 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
1041 int arg1, int arg2, Object obj) {
1042 super(context, handler, cmdName, cmd, arg1, arg2, obj);
1043 }
1044
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001045 @Override
1046 public void schedule(long when) {
1047 long delayMs = when - SystemClock.elapsedRealtime();
1048 if (delayMs < 0) delayMs = 0;
1049 if (delayMs > UNREASONABLY_LONG_WAIT) {
1050 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
1051 "ms into the future: " + delayMs);
1052 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001053 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
1054 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001055 }
1056
1057 @Override
1058 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001059 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001060 }
1061
1062 @Override
1063 public void onAlarm() {
1064 throw new AssertionError("Should never happen. Update this fake.");
1065 }
1066 }
1067
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001068 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +09001069 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001070 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -04001071
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001072 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001073 super(c, h, r);
1074 }
1075
1076 @Override
1077 public boolean configRestrictsAvoidBadWifi() {
1078 return configRestrictsAvoidBadWifi;
1079 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001080
1081 @Override
1082 public int configMeteredMultipathPreference() {
1083 return configMeteredMultipathPreference;
1084 }
Erik Kline065ab6e2016-10-02 18:02:14 +09001085 }
1086
1087 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001088 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001089 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +09001090
Paul Jensend7b6ca92015-05-13 14:05:12 -04001091 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001092 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Luke Huang65914772019-03-16 00:31:46 +08001093 IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) {
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001094 super(context, netManager, statsService, policyManager, dnsResolver, log, netd);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001095 mNetd = netd;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001096 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001097 }
1098
1099 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001100 protected MockableSystemProperties getSystemProperties() {
1101 // Minimal approach to overriding system properties: let most calls fall through to real
1102 // device values, and only override ones values that are important to this test.
1103 mSystemProperties = spy(new MockableSystemProperties());
1104 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1105 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1106 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001107 }
Paul Jensen67b0b072015-06-10 11:22:17 -04001108
1109 @Override
Mike Yuf9729752018-08-17 15:22:05 +08001110 protected Tethering makeTethering() {
1111 return mock(Tethering.class);
1112 }
1113
1114 @Override
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001115 protected ProxyTracker makeProxyTracker() {
1116 return mock(ProxyTracker.class);
1117 }
1118
1119 @Override
Paul Jensen67b0b072015-06-10 11:22:17 -04001120 protected int reserveNetId() {
1121 while (true) {
1122 final int netId = super.reserveNetId();
1123
1124 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1125 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001126 Context context = InstrumentationRegistry.getContext();
1127 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -04001128 boolean overlaps = false;
1129 for (Network network : networks) {
1130 if (netId == network.netId) {
1131 overlaps = true;
1132 break;
1133 }
1134 }
1135 if (overlaps) continue;
1136
1137 return netId;
1138 }
1139 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001140
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001141 @Override
1142 protected boolean queryUserAccess(int uid, int netId) {
1143 return true;
1144 }
1145
junyulai4a192e22018-06-13 15:00:37 +08001146 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1147 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1148 }
1149
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001150 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001151 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +09001152 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001153 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +09001154 return tracker;
1155 }
1156
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001157 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1158 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001159 }
1160
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001161 @Override
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +09001162 protected NetworkStackClient getNetworkStack() {
1163 return mNetworkStack;
1164 }
1165
1166 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +09001167 public WakeupMessage makeWakeupMessage(
1168 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1169 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001170 }
1171
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001172 @Override
1173 public boolean hasService(String name) {
1174 // Currenty, the only relevant service that ConnectivityService checks for is
1175 // ETHERNET_SERVICE.
1176 return Context.ETHERNET_SERVICE.equals(name);
1177 }
1178
Hugo Benichi64901e52017-10-19 14:42:40 +09001179 @Override
1180 protected IpConnectivityMetrics.Logger metricsLogger() {
1181 return mMetricsService;
1182 }
1183
dalyk1fcb7392018-03-05 12:42:22 -05001184 @Override
1185 protected void registerNetdEventCallback() {
1186 }
1187
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001188 public void mockVpn(int uid) {
1189 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001190 int userId = UserHandle.getUserId(uid);
1191 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001192 // This has no effect unless the VPN is actually connected, because things like
1193 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1194 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001195 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001196 }
1197 }
1198
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001199 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001200 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001201 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001202
1203 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001204 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001205 }
Mike Yuf9729752018-08-17 15:22:05 +08001206
1207 public void setUidRulesChanged(int uidRules) {
1208 try {
1209 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1210 } catch (RemoteException ignored) {
1211 }
1212 }
1213
1214 public void setRestrictBackgroundChanged(boolean restrictBackground) {
1215 try {
1216 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1217 } catch (RemoteException ignored) {
1218 }
1219 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001220 }
1221
Paul Jensen3d911462015-06-12 06:40:24 -04001222 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001223 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1224 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001225 */
1226 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001227 if (conditionVariable.block(TIMEOUT_MS)) {
1228 return;
1229 }
1230 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001231 }
1232
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001233 private static final int VPN_USER = 0;
1234 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1235 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1236 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1237
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001238 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001239 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001240 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001241
Hugo Benichi64901e52017-10-19 14:42:40 +09001242 MockitoAnnotations.initMocks(this);
1243 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1244
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001245 when(mUserManager.getUsers(eq(true))).thenReturn(
1246 Arrays.asList(new UserInfo[] {
1247 new UserInfo(VPN_USER, "", 0),
1248 }));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001249
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001250 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1251 // http://b/25897652 .
1252 if (Looper.myLooper() == null) {
1253 Looper.prepare();
1254 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001255 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001256
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001257 FakeSettingsProvider.clearSettingsProvider();
1258 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1259 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001260 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1261 LocalServices.addService(
1262 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001263
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001264 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001265 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001266 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001267 mNpm,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001268 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001269 mMockNetd,
1270 mMockDnsResolver);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001271
Mike Yuf9729752018-08-17 15:22:05 +08001272 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1273 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1274 verify(mNpm).registerListener(policyListenerCaptor.capture());
1275 mPolicyListener = policyListenerCaptor.getValue();
1276
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001277 // Create local CM before sending system ready so that we can answer
1278 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001279 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001280 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001281 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001282 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001283
1284 // Ensure that the default setting for Captive Portals is used for most tests
1285 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001286 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001287 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001288 }
1289
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001290 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001291 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001292 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001293 if (mCellNetworkAgent != null) {
1294 mCellNetworkAgent.disconnect();
1295 mCellNetworkAgent = null;
1296 }
1297 if (mWiFiNetworkAgent != null) {
1298 mWiFiNetworkAgent.disconnect();
1299 mWiFiNetworkAgent = null;
1300 }
1301 if (mEthernetNetworkAgent != null) {
1302 mEthernetNetworkAgent.disconnect();
1303 mEthernetNetworkAgent = null;
1304 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001305 FakeSettingsProvider.clearSettingsProvider();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001306 }
1307
Rubin Xu9e64dc02019-04-23 18:04:14 +01001308 private void mockDefaultPackages() throws Exception {
1309 final String testPackageName = mContext.getPackageName();
1310 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1311 testPackageName, PackageManager.GET_PERMISSIONS);
1312 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1313 new String[] {testPackageName});
1314 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1315 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1316
1317 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1318 Arrays.asList(new PackageInfo[] {
1319 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1320 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1321 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1322 }));
1323 }
1324
1325 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001326 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001327 case TRANSPORT_ETHERNET:
1328 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001329 case TRANSPORT_WIFI:
1330 return TYPE_WIFI;
1331 case TRANSPORT_CELLULAR:
1332 return TYPE_MOBILE;
1333 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001334 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001335 }
1336 }
1337
1338 private void verifyActiveNetwork(int transport) {
1339 // Test getActiveNetworkInfo()
1340 assertNotNull(mCm.getActiveNetworkInfo());
1341 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1342 // Test getActiveNetwork()
1343 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001344 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001345 if (!NetworkCapabilities.isValidTransport(transport)) {
1346 throw new IllegalStateException("Unknown transport " + transport);
1347 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001348 switch (transport) {
1349 case TRANSPORT_WIFI:
1350 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1351 break;
1352 case TRANSPORT_CELLULAR:
1353 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1354 break;
1355 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001356 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001357 }
1358 // Test getNetworkInfo(Network)
1359 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001360 assertEquals(transportToLegacyType(transport),
1361 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001362 // Test getNetworkCapabilities(Network)
1363 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1364 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1365 }
1366
1367 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001368 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001369 // Test getActiveNetworkInfo()
1370 assertNull(mCm.getActiveNetworkInfo());
1371 // Test getActiveNetwork()
1372 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001373 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001374 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001375 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001376 }
1377
1378 /**
1379 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1380 * broadcasts are received.
1381 */
1382 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1383 final ConditionVariable cv = new ConditionVariable();
1384 mServiceContext.registerReceiver(new BroadcastReceiver() {
1385 private int remaining = count;
1386 public void onReceive(Context context, Intent intent) {
1387 if (--remaining == 0) {
1388 cv.open();
1389 mServiceContext.unregisterReceiver(this);
1390 }
1391 }
1392 }, new IntentFilter(CONNECTIVITY_ACTION));
1393 return cv;
1394 }
1395
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001396 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001397 public void testNetworkTypes() {
1398 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1399 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1400 // will fail. Failing here is much easier to debug.
1401 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1402 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001403 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1404 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1405
1406 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1407 // mocks, this assert exercises the ConnectivityService code path that ensures that
1408 // TYPE_ETHERNET is supported if the ethernet service is running.
1409 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001410 }
1411
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001412 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001413 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001414 verifyNoNetwork();
1415 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1416 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1417 assertNull(mCm.getActiveNetworkInfo());
1418 assertNull(mCm.getActiveNetwork());
1419 // Test bringing up validated cellular.
1420 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1421 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001422 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001423 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001424 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001425 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1426 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1427 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1428 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1429 // Test bringing up validated WiFi.
1430 cv = waitForConnectivityBroadcasts(2);
1431 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001432 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001433 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001434 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001435 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1436 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1437 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1438 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1439 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001440 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001441 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001442 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001443 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001444 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001445 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1446 // Test WiFi disconnect.
1447 cv = waitForConnectivityBroadcasts(1);
1448 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001449 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001450 verifyNoNetwork();
1451 }
1452
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001453 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001454 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1455 // Test bringing up unvalidated WiFi
1456 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1457 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1458 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001459 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001460 verifyActiveNetwork(TRANSPORT_WIFI);
1461 // Test bringing up unvalidated cellular
1462 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1463 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001464 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001465 verifyActiveNetwork(TRANSPORT_WIFI);
1466 // Test cellular disconnect.
1467 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001468 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001469 verifyActiveNetwork(TRANSPORT_WIFI);
1470 // Test bringing up validated cellular
1471 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1472 cv = waitForConnectivityBroadcasts(2);
1473 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001474 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001475 verifyActiveNetwork(TRANSPORT_CELLULAR);
1476 // Test cellular disconnect.
1477 cv = waitForConnectivityBroadcasts(2);
1478 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001479 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001480 verifyActiveNetwork(TRANSPORT_WIFI);
1481 // Test WiFi disconnect.
1482 cv = waitForConnectivityBroadcasts(1);
1483 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001484 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001485 verifyNoNetwork();
1486 }
1487
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001488 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001489 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1490 // Test bringing up unvalidated cellular.
1491 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1492 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1493 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001494 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001495 verifyActiveNetwork(TRANSPORT_CELLULAR);
1496 // Test bringing up unvalidated WiFi.
1497 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1498 cv = waitForConnectivityBroadcasts(2);
1499 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001500 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001501 verifyActiveNetwork(TRANSPORT_WIFI);
1502 // Test WiFi disconnect.
1503 cv = waitForConnectivityBroadcasts(2);
1504 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001505 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001506 verifyActiveNetwork(TRANSPORT_CELLULAR);
1507 // Test cellular disconnect.
1508 cv = waitForConnectivityBroadcasts(1);
1509 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001510 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001511 verifyNoNetwork();
1512 }
1513
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001514 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001515 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001516 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001517 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001518 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1519 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001520 waitFor(cv);
1521 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001522 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001523 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001524 // Test bringing up validated cellular.
1525 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001526 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001527 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001528 waitFor(cv);
1529 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001530 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1531 NET_CAPABILITY_VALIDATED));
1532 // Test cellular disconnect.
1533 cv = waitForConnectivityBroadcasts(2);
1534 mCellNetworkAgent.disconnect();
1535 waitFor(cv);
1536 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001537 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001538 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001539 NET_CAPABILITY_VALIDATED));
1540 }
1541
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001542 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001543 public void testCellularOutscoresWeakWifi() throws Exception {
1544 // Test bringing up validated cellular.
1545 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1546 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1547 mCellNetworkAgent.connect(true);
1548 waitFor(cv);
1549 verifyActiveNetwork(TRANSPORT_CELLULAR);
1550 // Test bringing up validated WiFi.
1551 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1552 cv = waitForConnectivityBroadcasts(2);
1553 mWiFiNetworkAgent.connect(true);
1554 waitFor(cv);
1555 verifyActiveNetwork(TRANSPORT_WIFI);
1556 // Test WiFi getting really weak.
1557 cv = waitForConnectivityBroadcasts(2);
1558 mWiFiNetworkAgent.adjustScore(-11);
1559 waitFor(cv);
1560 verifyActiveNetwork(TRANSPORT_CELLULAR);
1561 // Test WiFi restoring signal strength.
1562 cv = waitForConnectivityBroadcasts(2);
1563 mWiFiNetworkAgent.adjustScore(11);
1564 waitFor(cv);
1565 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001566 }
1567
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001568 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001569 public void testReapingNetwork() throws Exception {
1570 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1571 // Expect it to be torn down immediately because it satisfies no requests.
1572 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1573 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1574 mWiFiNetworkAgent.connectWithoutInternet();
1575 waitFor(cv);
1576 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1577 // Expect it to be torn down immediately because it satisfies no requests.
1578 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1579 cv = mCellNetworkAgent.getDisconnectedCV();
1580 mCellNetworkAgent.connectWithoutInternet();
1581 waitFor(cv);
1582 // Test bringing up validated WiFi.
1583 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1584 cv = waitForConnectivityBroadcasts(1);
1585 mWiFiNetworkAgent.connect(true);
1586 waitFor(cv);
1587 verifyActiveNetwork(TRANSPORT_WIFI);
1588 // Test bringing up unvalidated cellular.
1589 // Expect it to be torn down because it could never be the highest scoring network
1590 // satisfying the default request even if it validated.
1591 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1592 cv = mCellNetworkAgent.getDisconnectedCV();
1593 mCellNetworkAgent.connect(false);
1594 waitFor(cv);
1595 verifyActiveNetwork(TRANSPORT_WIFI);
1596 cv = mWiFiNetworkAgent.getDisconnectedCV();
1597 mWiFiNetworkAgent.disconnect();
1598 waitFor(cv);
1599 }
1600
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001601 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001602 public void testCellularFallback() throws Exception {
1603 // Test bringing up validated cellular.
1604 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1605 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1606 mCellNetworkAgent.connect(true);
1607 waitFor(cv);
1608 verifyActiveNetwork(TRANSPORT_CELLULAR);
1609 // Test bringing up validated WiFi.
1610 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1611 cv = waitForConnectivityBroadcasts(2);
1612 mWiFiNetworkAgent.connect(true);
1613 waitFor(cv);
1614 verifyActiveNetwork(TRANSPORT_WIFI);
1615 // Reevaluate WiFi (it'll instantly fail DNS).
1616 cv = waitForConnectivityBroadcasts(2);
1617 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1618 NET_CAPABILITY_VALIDATED));
1619 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1620 // Should quickly fall back to Cellular.
1621 waitFor(cv);
1622 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1623 NET_CAPABILITY_VALIDATED));
1624 verifyActiveNetwork(TRANSPORT_CELLULAR);
1625 // Reevaluate cellular (it'll instantly fail DNS).
1626 cv = waitForConnectivityBroadcasts(2);
1627 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1628 NET_CAPABILITY_VALIDATED));
1629 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1630 // Should quickly fall back to WiFi.
1631 waitFor(cv);
1632 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1633 NET_CAPABILITY_VALIDATED));
1634 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1635 NET_CAPABILITY_VALIDATED));
1636 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001637 }
1638
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001639 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001640 public void testWiFiFallback() throws Exception {
1641 // Test bringing up unvalidated WiFi.
1642 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1643 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1644 mWiFiNetworkAgent.connect(false);
1645 waitFor(cv);
1646 verifyActiveNetwork(TRANSPORT_WIFI);
1647 // Test bringing up validated cellular.
1648 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1649 cv = waitForConnectivityBroadcasts(2);
1650 mCellNetworkAgent.connect(true);
1651 waitFor(cv);
1652 verifyActiveNetwork(TRANSPORT_CELLULAR);
1653 // Reevaluate cellular (it'll instantly fail DNS).
1654 cv = waitForConnectivityBroadcasts(2);
1655 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1656 NET_CAPABILITY_VALIDATED));
1657 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1658 // Should quickly fall back to WiFi.
1659 waitFor(cv);
1660 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1661 NET_CAPABILITY_VALIDATED));
1662 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001663 }
1664
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001665 @Test
1666 public void testRequiresValidation() {
1667 assertTrue(NetworkMonitorUtils.isValidationRequired(
1668 mCm.getDefaultRequest().networkCapabilities));
1669 }
1670
Paul Jensen3d911462015-06-12 06:40:24 -04001671 enum CallbackState {
1672 NONE,
1673 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001674 NETWORK_CAPABILITIES,
1675 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001676 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001677 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001678 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001679 LOST,
Mike Yuf9729752018-08-17 15:22:05 +08001680 UNAVAILABLE,
1681 BLOCKED_STATUS
Paul Jensen3d911462015-06-12 06:40:24 -04001682 }
1683
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001684 private static class CallbackInfo {
1685 public final CallbackState state;
1686 public final Network network;
1687 public final Object arg;
1688 public CallbackInfo(CallbackState s, Network n, Object o) {
1689 state = s; network = n; arg = o;
1690 }
1691 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001692 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001693 }
1694 @Override
1695 public boolean equals(Object o) {
1696 if (!(o instanceof CallbackInfo)) return false;
1697 // Ignore timeMs, since it's unpredictable.
1698 CallbackInfo other = (CallbackInfo) o;
1699 return (state == other.state) && Objects.equals(network, other.network);
1700 }
1701 @Override
1702 public int hashCode() {
1703 return Objects.hash(state, network);
1704 }
1705 }
1706
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001707 /**
1708 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1709 * this class receives, by calling expectCallback() exactly once each time a callback is
1710 * received. assertNoCallback may be called at any time.
1711 */
Paul Jensen3d911462015-06-12 06:40:24 -04001712 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001713 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001714 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001715
Erik Klineacdd6392016-07-07 16:50:58 +09001716 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001717 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001718 }
Paul Jensen3d911462015-06-12 06:40:24 -04001719
Erik Klineacdd6392016-07-07 16:50:58 +09001720 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001721 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001722 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001723 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001724 }
1725
Erik Klineacdd6392016-07-07 16:50:58 +09001726 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001727 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1728 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1729 }
1730
1731 @Override
1732 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1733 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1734 }
1735
1736 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001737 public void onUnavailable() {
1738 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1739 }
1740
1741 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001742 public void onNetworkSuspended(Network network) {
1743 setLastCallback(CallbackState.SUSPENDED, network, null);
1744 }
1745
1746 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001747 public void onNetworkResumed(Network network) {
1748 setLastCallback(CallbackState.RESUMED, network, null);
1749 }
1750
1751 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001752 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001753 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001754 }
1755
Erik Klineacdd6392016-07-07 16:50:58 +09001756 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001757 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001758 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001759 setLastCallback(CallbackState.LOST, network, null);
1760 }
1761
Mike Yuf9729752018-08-17 15:22:05 +08001762 @Override
1763 public void onBlockedStatusChanged(Network network, boolean blocked) {
1764 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1765 }
1766
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001767 public Network getLastAvailableNetwork() {
1768 return mLastAvailableNetwork;
1769 }
1770
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001771 CallbackInfo nextCallback(int timeoutMs) {
1772 CallbackInfo cb = null;
1773 try {
1774 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1775 } catch (InterruptedException e) {
1776 }
1777 if (cb == null) {
1778 // LinkedBlockingQueue.poll() returns null if it timeouts.
1779 fail("Did not receive callback after " + timeoutMs + "ms");
1780 }
1781 return cb;
1782 }
1783
Erik Kline1d3db322017-02-28 16:20:20 +09001784 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1785 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1786 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001787 CallbackInfo actual = nextCallback(timeoutMs);
1788 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001789
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001790 if (state == CallbackState.LOSING) {
1791 String msg = String.format(
1792 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001793 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001794 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001795 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001796 }
Erik Kline1d3db322017-02-28 16:20:20 +09001797
1798 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001799 }
1800
Erik Kline1d3db322017-02-28 16:20:20 +09001801 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001802 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001803 }
1804
Hugo Benichi16f0a942017-06-20 14:07:59 +09001805 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001806 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09001807 }
1808
1809 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1810 int timeLeft = timeoutMs;
1811 while (timeLeft > 0) {
1812 long start = SystemClock.elapsedRealtime();
1813 CallbackInfo info = nextCallback(timeLeft);
1814 if (fn.test(info)) {
1815 return info;
1816 }
1817 timeLeft -= (SystemClock.elapsedRealtime() - start);
1818 }
1819 fail("Did not receive expected callback after " + timeoutMs + "ms");
1820 return null;
1821 }
1822
Lorenzo Colitti27334542018-01-12 16:22:21 +09001823 // Expects onAvailable and the callbacks that follow it. These are:
1824 // - onSuspended, iff the network was suspended when the callbacks fire.
1825 // - onCapabilitiesChanged.
1826 // - onLinkPropertiesChanged.
Mike Yuf9729752018-08-17 15:22:05 +08001827 // - onBlockedStatusChanged.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001828 //
1829 // @param agent the network to expect the callbacks on.
1830 // @param expectSuspended whether to expect a SUSPENDED callback.
1831 // @param expectValidated the expected value of the VALIDATED capability in the
1832 // onCapabilitiesChanged callback.
1833 // @param timeoutMs how long to wait for the callbacks.
1834 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
Mike Yuf9729752018-08-17 15:22:05 +08001835 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001836 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001837 if (expectSuspended) {
1838 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001839 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001840 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001841 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001842 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001843 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001844 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001845 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Mike Yuf9729752018-08-17 15:22:05 +08001846 expectBlockedStatusCallback(expectBlocked, agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001847 }
1848
Lorenzo Colitti27334542018-01-12 16:22:21 +09001849 // Expects the available callbacks (validated), plus onSuspended.
1850 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
Mike Yuf9729752018-08-17 15:22:05 +08001851 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001852 }
1853
Lorenzo Colitti27334542018-01-12 16:22:21 +09001854 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001855 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1856 }
1857
1858 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1859 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001860 }
1861
Lorenzo Colitti27334542018-01-12 16:22:21 +09001862 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001863 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1864 }
1865
1866 void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1867 expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001868 }
1869
1870 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1871 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1872 // one we just sent.
1873 // TODO: this is likely a bug. Fix it and remove this method.
1874 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001875 expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001876 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001877 expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
Mike Yuf9729752018-08-17 15:22:05 +08001878 // Implicitly check the network is allowed to use.
1879 // TODO: should we need to consider if network is in blocked status in this case?
1880 expectBlockedStatusCallback(false, agent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001881 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1882 assertEquals(nc1, nc2);
1883 }
1884
1885 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1886 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1887 // when a network connects and satisfies a callback, and then immediately validates.
1888 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1889 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001890 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1891 }
1892
Lorenzo Colitti27334542018-01-12 16:22:21 +09001893 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001894 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001895 }
1896
1897 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1898 int timeoutMs) {
1899 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001900 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1901 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001902 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001903 }
1904
Lorenzo Colitti27334542018-01-12 16:22:21 +09001905 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001906 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001907 }
1908
1909 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1910 int timeoutMs) {
1911 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001912 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1913 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001914 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001915 }
1916
Chalard Jean0b214af2018-01-12 17:22:49 +09001917 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1918 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001919 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1920 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001921 }
1922
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09001923 void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1924 CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1925 assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1926 fn.test((LinkProperties) cbi.arg));
1927 }
1928
Mike Yuf9729752018-08-17 15:22:05 +08001929 void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1930 CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1931 boolean actualBlocked = (boolean) cbi.arg;
1932 assertEquals(expectBlocked, actualBlocked);
1933 }
1934
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001935 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001936 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001937 CallbackInfo c = mCallbacks.peek();
1938 assertNull("Unexpected callback: " + c, c);
1939 }
1940 }
1941
1942 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1943 // only be declared in a static or top level type".
1944 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1945 for (TestNetworkCallback c : callbacks) {
1946 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001947 }
1948 }
1949
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001950 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001951 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001952 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001953 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1954 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001955 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1956 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001957 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1958 .addTransportType(TRANSPORT_WIFI).build();
1959 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1960 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001961 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001962 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1963 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1964
1965 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001966 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1967 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1968 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001969 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1970 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001971 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1972 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001973 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001974
Paul Jensen3d911462015-06-12 06:40:24 -04001975 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1976 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001977 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001978 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001979 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1980
Paul Jensen3d911462015-06-12 06:40:24 -04001981 cv = waitForConnectivityBroadcasts(2);
1982 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1983 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001984 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1985 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001986 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1987 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001988 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001989
Paul Jensen3d911462015-06-12 06:40:24 -04001990 cv = waitForConnectivityBroadcasts(2);
1991 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001992 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1993 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001994 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001995 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001996 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001997
Paul Jensen3d911462015-06-12 06:40:24 -04001998 cv = waitForConnectivityBroadcasts(1);
1999 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002000 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2001 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
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
2005 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04002006 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2007 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002008 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2009 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002010 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002011 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002012
Paul Jensen3d911462015-06-12 06:40:24 -04002013 // This should not trigger spurious onAvailable() callbacks, b/21762680.
2014 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09002015 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002016 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002017 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2018
Paul Jensen3d911462015-06-12 06:40:24 -04002019 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2020 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002021 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002022 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002023 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002024 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002025 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002026 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002027 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002028
Paul Jensen3d911462015-06-12 06:40:24 -04002029 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002030 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2031 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2032 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002033
Paul Jensen3d911462015-06-12 06:40:24 -04002034 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002035 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2036 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2037 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002038 }
2039
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002040 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002041 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002042 // This test would be flaky with the default 120ms timer: that is short enough that
2043 // lingered networks are torn down before assertions can be run. We don't want to mock the
2044 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
2045 // in detecting races.
2046 mService.mLingerDelayMs = 300;
2047
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002048 NetworkRequest request = new NetworkRequest.Builder()
2049 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
2050 .build();
2051 TestNetworkCallback callback = new TestNetworkCallback();
2052 mCm.registerNetworkCallback(request, callback);
2053
2054 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2055 mCm.registerDefaultNetworkCallback(defaultCallback);
2056
2057 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2058 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2059 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2060
2061 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2062 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2063 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2064
2065 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002066 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2067 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002068 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002069 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002070
2071 mWiFiNetworkAgent.connect(true);
2072 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
2073 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002074 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002075 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002076 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002077 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002078 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002079 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002080 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002081
2082 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002083 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002084 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002085 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002086 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002087 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002088 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002089 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002090
2091 mEthernetNetworkAgent.disconnect();
2092 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2093 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002094 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002095 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002096
2097 for (int i = 0; i < 4; i++) {
2098 MockNetworkAgent oldNetwork, newNetwork;
2099 if (i % 2 == 0) {
2100 mWiFiNetworkAgent.adjustScore(-15);
2101 oldNetwork = mWiFiNetworkAgent;
2102 newNetwork = mCellNetworkAgent;
2103 } else {
2104 mWiFiNetworkAgent.adjustScore(15);
2105 oldNetwork = mCellNetworkAgent;
2106 newNetwork = mWiFiNetworkAgent;
2107
2108 }
2109 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002110 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2111 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002112 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002113 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2114 }
2115 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2116
2117 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2118 // if the network is still up.
2119 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002120 // We expect a notification about the capabilities change, and nothing else.
2121 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2122 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002123 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002124 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002125
2126 // Wifi no longer satisfies our listen, which is for an unmetered network.
2127 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002128 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2129
2130 // Disconnect our test networks.
2131 mWiFiNetworkAgent.disconnect();
2132 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002133 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002134 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002135 mCellNetworkAgent.disconnect();
2136 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002137 waitForIdle();
2138 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002139
2140 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002141 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002142
2143 // Check that a network is only lingered or torn down if it would not satisfy a request even
2144 // if it validated.
2145 request = new NetworkRequest.Builder().clearCapabilities().build();
2146 callback = new TestNetworkCallback();
2147
2148 mCm.registerNetworkCallback(request, callback);
2149
2150 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2151 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002152 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2153 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002154 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002155 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002156
2157 // Bring up wifi with a score of 20.
2158 // Cell stays up because it would satisfy the default request if it validated.
2159 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2160 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002161 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2162 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002163 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002164 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002165
2166 mWiFiNetworkAgent.disconnect();
2167 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2168 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002169 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002170 assertEquals(mCellNetworkAgent.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 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002174 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002175 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2176 mWiFiNetworkAgent.adjustScore(50);
2177 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002178 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002179 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002180 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002181 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002182 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002183
2184 // Tear down wifi.
2185 mWiFiNetworkAgent.disconnect();
2186 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2187 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002188 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002189 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002190 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002191
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002192 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2193 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002194 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2195 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002196 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002197 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002198 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002199 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002200 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002201 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002202 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002203
2204 mWiFiNetworkAgent.disconnect();
2205 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002206 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002207 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002208 mCellNetworkAgent.disconnect();
2209 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2210 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002211 waitForIdle();
2212 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002213
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002214 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002215 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2216 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002217 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2218 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002219 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002220 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2221 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002222 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2223 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002224 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002225 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002226 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002227 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002228
2229 NetworkRequest cellRequest = new NetworkRequest.Builder()
2230 .addTransportType(TRANSPORT_CELLULAR).build();
2231 NetworkCallback noopCallback = new NetworkCallback();
2232 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002233 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2234 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002235 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002236 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002237
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002238 // Similar to the above: lingering can start even after the lingered request is removed.
2239 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002240 mWiFiNetworkAgent.disconnect();
2241 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002242 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002243 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002244 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002245
2246 // Cell is now the default network. Pin it with a cell-specific request.
2247 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2248 mCm.requestNetwork(cellRequest, noopCallback);
2249
2250 // Now connect wifi, and expect it to become the default network.
2251 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2252 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002253 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2254 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002255 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002256 // The default request is lingering on cell, but nothing happens to cell, and we send no
2257 // callbacks for it, because it's kept up by cellRequest.
2258 callback.assertNoCallback();
2259 // Now unregister cellRequest and expect cell to start lingering.
2260 mCm.unregisterNetworkCallback(noopCallback);
2261 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2262
2263 // Let linger run its course.
2264 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002265 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002266 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002267
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002268 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2269 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2270 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002271 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002272 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2273 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002274 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002275 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2276 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002277 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2278 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002279 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002280
2281 // Let linger run its course.
2282 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2283
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002284 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002285 mEthernetNetworkAgent.disconnect();
2286 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2287 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2288 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002289
2290 mCm.unregisterNetworkCallback(callback);
2291 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002292 mCm.unregisterNetworkCallback(trackDefaultCallback);
2293 }
2294
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002295 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002296 public void testNetworkGoesIntoBackgroundAfterLinger() {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002297 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002298 NetworkRequest request = new NetworkRequest.Builder()
2299 .clearCapabilities()
2300 .build();
2301 TestNetworkCallback callback = new TestNetworkCallback();
2302 mCm.registerNetworkCallback(request, callback);
2303
2304 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2305 mCm.registerDefaultNetworkCallback(defaultCallback);
2306
2307 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2308 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2309
2310 mCellNetworkAgent.connect(true);
2311 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2312 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2313
2314 // Wifi comes up and cell lingers.
2315 mWiFiNetworkAgent.connect(true);
2316 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2317 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2318 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2319 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2320
2321 // File a request for cellular, then release it.
2322 NetworkRequest cellRequest = new NetworkRequest.Builder()
2323 .addTransportType(TRANSPORT_CELLULAR).build();
2324 NetworkCallback noopCallback = new NetworkCallback();
2325 mCm.requestNetwork(cellRequest, noopCallback);
2326 mCm.unregisterNetworkCallback(noopCallback);
2327 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2328
2329 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002330 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002331 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2332 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2333 lingerTimeoutMs);
2334
2335 // Clean up.
2336 mCm.unregisterNetworkCallback(defaultCallback);
2337 mCm.unregisterNetworkCallback(callback);
2338 }
2339
2340 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002341 public void testExplicitlySelected() {
2342 NetworkRequest request = new NetworkRequest.Builder()
2343 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2344 .build();
2345 TestNetworkCallback callback = new TestNetworkCallback();
2346 mCm.registerNetworkCallback(request, callback);
2347
2348 // Bring up validated cell.
2349 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2350 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002351 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002352
2353 // Bring up unvalidated wifi with explicitlySelected=true.
2354 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2355 mWiFiNetworkAgent.explicitlySelected(false);
2356 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002357 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002358
2359 // Cell Remains the default.
2360 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2361
2362 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2363 // it's explicitly selected.
2364 mWiFiNetworkAgent.adjustScore(-40);
2365 mWiFiNetworkAgent.adjustScore(40);
2366 callback.assertNoCallback();
2367
2368 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2369 // wifi even though it's unvalidated.
2370 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2371 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2372 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2373
2374 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2375 mWiFiNetworkAgent.disconnect();
2376 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2377 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2378 mWiFiNetworkAgent.explicitlySelected(false);
2379 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002380 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002381
2382 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2383 // network to disconnect.
2384 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2385 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2386
2387 // Reconnect, again with explicitlySelected=true, but this time validate.
2388 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2389 mWiFiNetworkAgent.explicitlySelected(false);
2390 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002391 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002392 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2393 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2394 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2395
2396 // BUG: the network will no longer linger, even though it's validated and outscored.
2397 // TODO: fix this.
2398 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2399 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002400 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002401 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2402 callback.assertNoCallback();
2403
2404 // Clean up.
2405 mWiFiNetworkAgent.disconnect();
2406 mCellNetworkAgent.disconnect();
2407 mEthernetNetworkAgent.disconnect();
2408
2409 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2410 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2411 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002412 }
2413
Chalard Jean05ab6812018-05-02 21:14:54 +09002414 private int[] makeIntArray(final int size, final int value) {
2415 final int[] array = new int[size];
2416 Arrays.fill(array, value);
2417 return array;
2418 }
2419
Paul Jensen85cf78e2015-06-25 13:25:07 -04002420 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002421 // Verify NOT_RESTRICTED is set appropriately
2422 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2423 .build().networkCapabilities;
2424 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2425 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2426 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002427 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002428 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2429 } else {
2430 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2431 }
2432
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002433 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002434 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002435 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2436 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002437 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002438 mServiceContext, "testFactory", filter);
2439 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002440 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002441 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002442 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002443 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002444 int expectedRequestCount = 1;
2445 NetworkCallback networkCallback = null;
2446 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2447 // add one.
2448 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002449 assertFalse(testFactory.getMyStartRequested());
2450 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2451 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002452 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002453 mCm.requestNetwork(request, networkCallback);
2454 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002455 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002456 }
Paul Jensen3d911462015-06-12 06:40:24 -04002457 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002458 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2459 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002460
Paul Jensen85cf78e2015-06-25 13:25:07 -04002461 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002462 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002463 // Rather than create a validated network which complicates things by registering it's
2464 // own NetworkRequest during startup, just bump up the score to cancel out the
2465 // unvalidated penalty.
2466 testAgent.adjustScore(40);
2467 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002468
2469 // When testAgent connects, ConnectivityService will re-send us all current requests with
2470 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2471 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002472 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002473 testAgent.connect(false);
2474 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002475 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002476 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002477 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002478
Paul Jensen85cf78e2015-06-25 13:25:07 -04002479 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002480 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002481 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002482 ConnectivityManager.NetworkCallback[] networkCallbacks =
2483 new ConnectivityManager.NetworkCallback[10];
2484 for (int i = 0; i< networkCallbacks.length; i++) {
2485 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2486 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002487 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002488 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2489 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002490 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2491 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002492
Paul Jensen85cf78e2015-06-25 13:25:07 -04002493 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002494 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002495 for (int i = 0; i < networkCallbacks.length; i++) {
2496 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2497 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002498 testFactory.waitForNetworkRequests(expectedRequestCount);
2499 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002500
Paul Jensen85cf78e2015-06-25 13:25:07 -04002501 // Drop the higher scored network.
2502 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002503 // With the default network disconnecting, the requests are sent with score 0 to factories.
2504 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002505 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002506 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002507 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002508 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2509 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002510
2511 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002512 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002513 handlerThread.quit();
2514 }
2515
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002516 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002517 public void testNetworkFactoryRequests() throws Exception {
2518 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2519 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2520 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2521 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2522 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2523 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2524 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2525 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2526 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2527 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2528 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2529 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2530 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2531 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2532 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2533 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2534 }
2535
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002536 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002537 public void testNoMutableNetworkRequests() throws Exception {
2538 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002539 NetworkRequest request1 = new NetworkRequest.Builder()
2540 .addCapability(NET_CAPABILITY_VALIDATED)
2541 .build();
2542 NetworkRequest request2 = new NetworkRequest.Builder()
2543 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2544 .build();
2545
2546 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2547 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2548 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2549 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2550 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002551 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002552
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002553 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002554 public void testMMSonWiFi() throws Exception {
2555 // Test bringing up cellular without MMS NetworkRequest gets reaped
2556 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2557 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2558 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2559 mCellNetworkAgent.connectWithoutInternet();
2560 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002561 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002562 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002563 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002564
Paul Jensene0988542015-06-25 15:30:08 -04002565 // Test bringing up validated WiFi.
2566 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2567 cv = waitForConnectivityBroadcasts(1);
2568 mWiFiNetworkAgent.connect(true);
2569 waitFor(cv);
2570 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002571
Paul Jensene0988542015-06-25 15:30:08 -04002572 // Register MMS NetworkRequest
2573 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2574 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2575 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2576 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002577
Paul Jensene0988542015-06-25 15:30:08 -04002578 // Test bringing up unvalidated cellular with MMS
2579 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2580 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002581 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002582 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002583 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002584
Paul Jensene0988542015-06-25 15:30:08 -04002585 // Test releasing NetworkRequest disconnects cellular with MMS
2586 cv = mCellNetworkAgent.getDisconnectedCV();
2587 mCm.unregisterNetworkCallback(networkCallback);
2588 waitFor(cv);
2589 verifyActiveNetwork(TRANSPORT_WIFI);
2590 }
2591
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002592 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002593 public void testMMSonCell() throws Exception {
2594 // Test bringing up cellular without MMS
2595 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2596 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2597 mCellNetworkAgent.connect(false);
2598 waitFor(cv);
2599 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002600
Paul Jensene0988542015-06-25 15:30:08 -04002601 // Register MMS NetworkRequest
2602 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2603 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2604 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2605 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002606
Paul Jensene0988542015-06-25 15:30:08 -04002607 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002608 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2609 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2610 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002611 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002612 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002613
Paul Jensene0988542015-06-25 15:30:08 -04002614 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2615 cv = mmsNetworkAgent.getDisconnectedCV();
2616 mCm.unregisterNetworkCallback(networkCallback);
2617 waitFor(cv);
2618 verifyActiveNetwork(TRANSPORT_CELLULAR);
2619 }
2620
lucaslinf3b59b32019-03-26 17:49:49 +08002621 @Test
lucasline252a742019-03-12 13:08:03 +08002622 public void testPartialConnectivity() {
2623 // Register network callback.
2624 NetworkRequest request = new NetworkRequest.Builder()
2625 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2626 .build();
2627 TestNetworkCallback callback = new TestNetworkCallback();
2628 mCm.registerNetworkCallback(request, callback);
2629
2630 // Bring up validated mobile data.
2631 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2632 mCellNetworkAgent.connect(true);
2633 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2634
2635 // Bring up wifi with partial connectivity.
2636 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2637 mWiFiNetworkAgent.connectWithPartialConnectivity();
2638 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2639 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2640
2641 // Mobile data should be the default network.
2642 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2643 callback.assertNoCallback();
2644
lucaslinf3b59b32019-03-26 17:49:49 +08002645 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2646 // probe.
2647 mWiFiNetworkAgent.setNetworkValid();
lucasline252a742019-03-12 13:08:03 +08002648 // If the user chooses yes to use this partial connectivity wifi, switch the default
2649 // network to wifi and check if wifi becomes valid or not.
2650 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2651 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002652 // If user accepts partial connectivity network,
2653 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002654 waitForIdle();
2655 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002656 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002657 } catch (RemoteException e) {
2658 fail(e.getMessage());
2659 }
lucaslinf3b59b32019-03-26 17:49:49 +08002660 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2661 // validated.
2662 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
lucasline252a742019-03-12 13:08:03 +08002663 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2664 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2665 mWiFiNetworkAgent);
2666 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2667 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2668
2669 // Disconnect and reconnect wifi with partial connectivity again.
2670 mWiFiNetworkAgent.disconnect();
2671 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2672 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2673 mWiFiNetworkAgent.connectWithPartialConnectivity();
2674 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2675 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2676
2677 // Mobile data should be the default network.
2678 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2679
2680 // If the user chooses no, disconnect wifi immediately.
2681 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2682 false /* always */);
2683 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2684
2685 // If user accepted partial connectivity before, and device reconnects to that network
2686 // again, but now the network has full connectivity. The network shouldn't contain
2687 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2688 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2689 // acceptUnvalidated is also used as setting for accepting partial networks.
2690 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
2691 mWiFiNetworkAgent.connect(true);
lucaslinf3b59b32019-03-26 17:49:49 +08002692 // If user accepted partial connectivity network before,
2693 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2694 // ConnectivityService#updateNetworkInfo().
2695 waitForIdle();
2696 try {
2697 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2698 } catch (RemoteException e) {
2699 fail(e.getMessage());
2700 }
lucasline252a742019-03-12 13:08:03 +08002701 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2702 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2703 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2704 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2705 // Wifi should be the default network.
2706 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2707 mWiFiNetworkAgent.disconnect();
2708 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2709
2710 // If user accepted partial connectivity before, and now the device reconnects to the
2711 // partial connectivity network. The network should be valid and contain
2712 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2713 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2714 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
lucaslinf3b59b32019-03-26 17:49:49 +08002715 // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
2716 // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
2717 // to ConnectivityService first then send VALID. Once NetworkMonitor support
2718 // multi-testResult, this test case also need to be changed to meet the new design.
lucasline252a742019-03-12 13:08:03 +08002719 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002720 // If user accepted partial connectivity network before,
2721 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2722 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002723 waitForIdle();
2724 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002725 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002726 } catch (RemoteException e) {
2727 fail(e.getMessage());
2728 }
lucaslinf3b59b32019-03-26 17:49:49 +08002729 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002730 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
lucaslinf3b59b32019-03-26 17:49:49 +08002731 // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
2732 // NetworkMonitor detects partial connectivity
lucasline252a742019-03-12 13:08:03 +08002733 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002734 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2735 mWiFiNetworkAgent.setNetworkValid();
2736 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2737 // validated.
2738 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2739 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2740 mWiFiNetworkAgent.disconnect();
2741 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002742 }
2743
2744 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002745 public void testCaptivePortal() {
2746 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2747 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2748 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2749 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2750
2751 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2752 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2753 .addCapability(NET_CAPABILITY_VALIDATED).build();
2754 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002755
2756 // Bring up a network with a captive portal.
2757 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002758 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002759 String firstRedirectUrl = "http://example.com/firstPath";
2760 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002761 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002762 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002763
2764 // Take down network.
2765 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002766 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002767 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002768
2769 // Bring up a network with a captive portal.
2770 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002771 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002772 String secondRedirectUrl = "http://example.com/secondPath";
2773 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002774 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002775 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002776
2777 // Make captive portal disappear then revalidate.
2778 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002779 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002780 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002781 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002782
2783 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002784 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002785
2786 // Break network connectivity.
2787 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002788 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002789 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002790 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002791 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002792
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002793 @Test
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002794 public void testCaptivePortalApp() throws RemoteException {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002795 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2796 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2797 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2798 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2799
2800 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2801 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2802 .addCapability(NET_CAPABILITY_VALIDATED).build();
2803 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2804
2805 // Bring up wifi.
2806 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2807 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002808 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002809 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2810
2811 // Check that calling startCaptivePortalApp does nothing.
2812 final int fastTimeoutMs = 100;
2813 mCm.startCaptivePortalApp(wifiNetwork);
2814 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2815
2816 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002817 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002818 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002819 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002820 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2821
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002822 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002823 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002824 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2825 .launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002826
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002827 // Report that the captive portal is dismissed, and check that callbacks are fired
2828 mWiFiNetworkAgent.setNetworkValid();
2829 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002830 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002831 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2832
2833 mCm.unregisterNetworkCallback(validatedCallback);
2834 mCm.unregisterNetworkCallback(captivePortalCallback);
2835 }
2836
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002837 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002838 public void testAvoidOrIgnoreCaptivePortals() {
2839 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2840 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2841 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2842 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2843
2844 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2845 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2846 .addCapability(NET_CAPABILITY_VALIDATED).build();
2847 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2848
2849 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2850 // Bring up a network with a captive portal.
2851 // Expect it to fail to connect and not result in any callbacks.
2852 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2853 String firstRedirectUrl = "http://example.com/firstPath";
2854
2855 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2856 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2857 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2858 waitFor(disconnectCv);
2859 waitFor(avoidCv);
2860
2861 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002862 }
2863
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002864 private NetworkRequest.Builder newWifiRequestBuilder() {
2865 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2866 }
2867
Etan Cohen836ad572018-12-30 17:59:59 -08002868 /**
2869 * Verify request matching behavior with network specifiers.
2870 *
2871 * Note: this test is somewhat problematic since it involves removing capabilities from
2872 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2873 * as a WTF bug in
2874 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2875 * does work.
2876 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002877 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002878 public void testNetworkSpecifier() {
Etan Cohen836ad572018-12-30 17:59:59 -08002879 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2880 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2881 Parcelable {
2882 @Override
2883 public boolean satisfiedBy(NetworkSpecifier other) {
2884 return true;
2885 }
2886
2887 @Override
2888 public int describeContents() {
2889 return 0;
2890 }
2891
2892 @Override
2893 public void writeToParcel(Parcel dest, int flags) {}
2894
2895 @Override
2896 public NetworkSpecifier redact() {
2897 return null;
2898 }
2899 }
2900
2901 // A network specifier that matches either another LocalNetworkSpecifier with the same
2902 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2903 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2904 private String mString;
2905
2906 LocalStringNetworkSpecifier(String string) {
2907 mString = string;
2908 }
2909
2910 @Override
2911 public boolean satisfiedBy(NetworkSpecifier other) {
2912 if (other instanceof LocalStringNetworkSpecifier) {
2913 return TextUtils.equals(mString,
2914 ((LocalStringNetworkSpecifier) other).mString);
2915 }
2916 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2917 return false;
2918 }
2919
2920 @Override
2921 public int describeContents() {
2922 return 0;
2923 }
2924 @Override
2925 public void writeToParcel(Parcel dest, int flags) {}
2926 }
2927
2928
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002929 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002930 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002931 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002932 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2933 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002934 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2935 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002936 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002937 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002938
2939 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2940 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2941 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002942 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002943 TestNetworkCallback cFoo = new TestNetworkCallback();
2944 TestNetworkCallback cBar = new TestNetworkCallback();
2945 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002946 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002947
2948 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2949 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2950 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002951 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002952 mCm.registerNetworkCallback(rFoo, cFoo);
2953 mCm.registerNetworkCallback(rBar, cBar);
2954
Etan Cohen836ad572018-12-30 17:59:59 -08002955 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2956 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2957
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002958 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2959 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002960 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2961 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2962 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2963 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002964 assertNoCallbacks(cFoo, cBar);
2965
Etan Cohen836ad572018-12-30 17:59:59 -08002966 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002967 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002968 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002969 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2970 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002971 }
Etan Cohen836ad572018-12-30 17:59:59 -08002972 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2973 mWiFiNetworkAgent);
2974 assertEquals(nsFoo,
2975 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002976 cFoo.assertNoCallback();
2977
Etan Cohen836ad572018-12-30 17:59:59 -08002978 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002979 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002980 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002981 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002982 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2983 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002984 }
Etan Cohen836ad572018-12-30 17:59:59 -08002985 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2986 mWiFiNetworkAgent);
2987 assertEquals(nsBar,
2988 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2989 cBar.assertNoCallback();
2990
2991 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2992 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2993 for (TestNetworkCallback c : emptyCallbacks) {
2994 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2995 mWiFiNetworkAgent);
2996 }
2997 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2998 mWiFiNetworkAgent);
2999 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3000 mWiFiNetworkAgent);
3001 assertNull(
3002 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3003 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003004 cBar.assertNoCallback();
3005
3006 mWiFiNetworkAgent.setNetworkSpecifier(null);
Etan Cohen836ad572018-12-30 17:59:59 -08003007 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003008 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3009 for (TestNetworkCallback c: emptyCallbacks) {
3010 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
3011 }
3012
Etan Cohen836ad572018-12-30 17:59:59 -08003013 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003014 }
3015
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003016 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08003017 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003018 try {
3019 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07003020 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
3021 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
3022 } catch (IllegalArgumentException expected) {
3023 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08003024 }
3025
Etan Cohenddb9ef02015-11-18 10:56:15 -08003026 try {
3027 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3028 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07003029 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08003030 mService.requestNetwork(networkCapabilities, null, 0, null,
3031 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07003032 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
3033 } catch (IllegalArgumentException expected) {
3034 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08003035 }
3036
Etan Cohena7434272017-04-03 12:17:51 -07003037 class NonParcelableSpecifier extends NetworkSpecifier {
3038 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
3039 };
3040 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3041 @Override public int describeContents() { return 0; }
3042 @Override public void writeToParcel(Parcel p, int flags) {}
3043 }
3044 NetworkRequest.Builder builder;
3045
3046 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3047 try {
3048 builder.setNetworkSpecifier(new NonParcelableSpecifier());
3049 Parcel parcelW = Parcel.obtain();
3050 builder.build().writeToParcel(parcelW, 0);
3051 fail("Parceling a non-parcelable specifier did not throw an exception");
3052 } catch (Exception e) {
3053 // expected
3054 }
3055
3056 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3057 builder.setNetworkSpecifier(new ParcelableSpecifier());
3058 NetworkRequest nr = builder.build();
3059 assertNotNull(nr);
3060
3061 try {
3062 Parcel parcelW = Parcel.obtain();
3063 nr.writeToParcel(parcelW, 0);
3064 byte[] bytes = parcelW.marshall();
3065 parcelW.recycle();
3066
3067 Parcel parcelR = Parcel.obtain();
3068 parcelR.unmarshall(bytes, 0, bytes.length);
3069 parcelR.setDataPosition(0);
3070 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
3071 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
3072 } catch (Exception e) {
3073 // expected
3074 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08003075 }
3076
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003077 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07003078 public void testNetworkSpecifierUidSpoofSecurityException() {
3079 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3080 @Override
3081 public boolean satisfiedBy(NetworkSpecifier other) {
3082 return true;
3083 }
3084
3085 @Override
3086 public void assertValidFromUid(int requestorUid) {
3087 throw new SecurityException("failure");
3088 }
3089
3090 @Override
3091 public int describeContents() { return 0; }
3092 @Override
3093 public void writeToParcel(Parcel dest, int flags) {}
3094 }
3095
3096 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3097 mWiFiNetworkAgent.connect(false);
3098
3099 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
3100 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
3101 networkSpecifier).build();
3102 TestNetworkCallback networkCallback = new TestNetworkCallback();
3103 try {
3104 mCm.requestNetwork(networkRequest, networkCallback);
3105 fail("Network request with spoofed UID did not throw a SecurityException");
3106 } catch (SecurityException e) {
3107 // expected
3108 }
3109 }
3110
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003111 @Test
paulhu3d67f532019-03-22 16:35:06 +08003112 public void testInvalidSignalStrength() {
3113 NetworkRequest r = new NetworkRequest.Builder()
3114 .addCapability(NET_CAPABILITY_INTERNET)
3115 .addTransportType(TRANSPORT_WIFI)
3116 .setSignalStrength(-75)
3117 .build();
3118 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3119 // permission should get SecurityException.
3120 try {
3121 mCm.registerNetworkCallback(r, new NetworkCallback());
3122 fail("Expected SecurityException filing a callback with signal strength");
3123 } catch (SecurityException expected) {
3124 // expected
3125 }
3126
3127 try {
3128 mCm.registerNetworkCallback(r, PendingIntent.getService(
3129 mServiceContext, 0, new Intent(), 0));
3130 fail("Expected SecurityException filing a callback with signal strength");
3131 } catch (SecurityException expected) {
3132 // expected
3133 }
3134
3135 // Requesting a Network with signal strength should get IllegalArgumentException.
3136 try {
3137 mCm.requestNetwork(r, new NetworkCallback());
3138 fail("Expected IllegalArgumentException filing a request with signal strength");
3139 } catch (IllegalArgumentException expected) {
3140 // expected
3141 }
3142
3143 try {
3144 mCm.requestNetwork(r, PendingIntent.getService(
3145 mServiceContext, 0, new Intent(), 0));
3146 fail("Expected IllegalArgumentException filing a request with signal strength");
3147 } catch (IllegalArgumentException expected) {
3148 // expected
3149 }
3150 }
3151
3152 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003153 public void testRegisterDefaultNetworkCallback() throws Exception {
3154 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3155 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3156 defaultNetworkCallback.assertNoCallback();
3157
3158 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3159 // whenever Wi-Fi is up. Without this, the mobile network agent is
3160 // reaped before any other activity can take place.
3161 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3162 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3163 .addTransportType(TRANSPORT_CELLULAR).build();
3164 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3165 cellNetworkCallback.assertNoCallback();
3166
3167 // Bring up cell and expect CALLBACK_AVAILABLE.
3168 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3169 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003170 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3171 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003172 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003173
3174 // Bring up wifi and expect CALLBACK_AVAILABLE.
3175 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3176 mWiFiNetworkAgent.connect(true);
3177 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003178 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003179 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003180
3181 // Bring down cell. Expect no default network callback, since it wasn't the default.
3182 mCellNetworkAgent.disconnect();
3183 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3184 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003185 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003186
3187 // Bring up cell. Expect no default network callback, since it won't be the default.
3188 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3189 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003190 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003191 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 down wifi. Expect the default network callback to notified of LOST wifi
3195 // followed by AVAILABLE cell.
3196 mWiFiNetworkAgent.disconnect();
3197 cellNetworkCallback.assertNoCallback();
3198 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003199 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003200 mCellNetworkAgent.disconnect();
3201 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3202 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003203 waitForIdle();
3204 assertEquals(null, mCm.getActiveNetwork());
3205
3206 final int uid = Process.myUid();
3207 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
3208 final ArraySet<UidRange> ranges = new ArraySet<>();
3209 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003210 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3211 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003212 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003213 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003214 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3215 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3216
3217 vpnNetworkAgent.disconnect();
3218 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3219 waitForIdle();
3220 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003221 }
3222
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003223 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003224 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003225 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003226 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003227 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3228 .addTransportType(TRANSPORT_CELLULAR).build();
3229 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3230
3231 // Bring up the mobile network.
3232 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3233 mCellNetworkAgent.connect(true);
3234
Erik Kline1d3db322017-02-28 16:20:20 +09003235 // We should get onAvailable(), onCapabilitiesChanged(), and
3236 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3237 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003238 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003239 cellNetworkCallback.assertNoCallback();
3240
3241 // Update LinkProperties.
3242 final LinkProperties lp = new LinkProperties();
3243 lp.setInterfaceName("foonet_data0");
3244 mCellNetworkAgent.sendLinkProperties(lp);
3245 // We should get onLinkPropertiesChanged().
3246 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
3247 cellNetworkCallback.assertNoCallback();
3248
Erik Kline1d3db322017-02-28 16:20:20 +09003249 // Suspend the network.
3250 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003251 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3252 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003253 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
3254 cellNetworkCallback.assertNoCallback();
3255
Erik Klineacdd6392016-07-07 16:50:58 +09003256 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003257 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003258 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003259 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3260 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003261 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003262 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003263 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3264
3265 mCellNetworkAgent.resume();
3266 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3267 mCellNetworkAgent);
3268 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
3269 cellNetworkCallback.assertNoCallback();
3270
3271 dfltNetworkCallback = new TestNetworkCallback();
3272 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3273 // This time onNetworkSuspended should not be called.
3274 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3275 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003276
Erik Klineacdd6392016-07-07 16:50:58 +09003277 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3278 mCm.unregisterNetworkCallback(cellNetworkCallback);
3279 }
3280
Calvin On1f64f3f2016-10-11 15:10:46 -07003281 private void setCaptivePortalMode(int mode) {
3282 ContentResolver cr = mServiceContext.getContentResolver();
3283 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3284 }
3285
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003286 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003287 ContentResolver cr = mServiceContext.getContentResolver();
3288 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003289 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003290 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003291 }
3292
Erik Kline79c6d052018-03-21 07:18:33 -07003293 private void setPrivateDnsSettings(String mode, String specifier) {
3294 final ContentResolver cr = mServiceContext.getContentResolver();
3295 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3296 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3297 mService.updatePrivateDnsSettings();
3298 waitForIdle();
3299 }
3300
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003301 private boolean isForegroundNetwork(MockNetworkAgent network) {
3302 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3303 assertNotNull(nc);
3304 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3305 }
3306
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003307 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003308 public void testBackgroundNetworks() throws Exception {
3309 // Create a background request. We can't do this ourselves because ConnectivityService
3310 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003311 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003312 final NetworkRequest request = new NetworkRequest.Builder().build();
3313 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3314 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3315 final TestNetworkCallback callback = new TestNetworkCallback();
3316 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3317 mCm.registerNetworkCallback(request, callback);
3318 mCm.registerNetworkCallback(fgRequest, fgCallback);
3319
3320 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3321 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003322 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3323 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003324 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3325
3326 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3327 mWiFiNetworkAgent.connect(true);
3328
3329 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003330 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003331 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003332 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003333 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003334 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003335 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003336 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3337 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3338
3339 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003340 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003341 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3342 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003343 // Expect a network capabilities update sans FOREGROUND.
3344 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003345 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3346 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3347
3348 // File a cell request and check that cell comes into the foreground.
3349 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3350 .addTransportType(TRANSPORT_CELLULAR).build();
3351 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3352 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003353 // NOTE: This request causes the network's capabilities to change. This
3354 // is currently delivered before the onAvailable() callbacks.
3355 // TODO: Fix this.
3356 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003357 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3358 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003359 // Expect a network capabilities update with FOREGROUND, because the most recent
3360 // request causes its state to change.
3361 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003362 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3363 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3364
3365 // Release the request. The network immediately goes into the background, since it was not
3366 // lingering.
3367 mCm.unregisterNetworkCallback(cellCallback);
3368 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003369 // Expect a network capabilities update sans FOREGROUND.
3370 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003371 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3372 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3373
3374 // Disconnect wifi and check that cell is foreground again.
3375 mWiFiNetworkAgent.disconnect();
3376 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3377 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003378 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003379 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3380
3381 mCm.unregisterNetworkCallback(callback);
3382 mCm.unregisterNetworkCallback(fgCallback);
3383 }
3384
Hugo Benichi849b81b2017-05-25 13:42:31 +09003385 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003386 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003387 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003388 // Benchmarks connecting and switching performance in the presence of a large number of
3389 // NetworkRequests.
3390 // 1. File NUM_REQUESTS requests.
3391 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3392 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3393 // and NUM_REQUESTS onAvailable callbacks to fire.
3394 // See how long it took.
3395 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003396 final int REGISTER_TIME_LIMIT_MS = 200;
3397 final int CONNECT_TIME_LIMIT_MS = 60;
3398 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003399 final int UNREGISTER_TIME_LIMIT_MS = 20;
3400
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003401 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3402 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3403 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3404 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3405
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003406 for (int i = 0; i < NUM_REQUESTS; i++) {
3407 callbacks[i] = new NetworkCallback() {
3408 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3409 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3410 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003411 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003412
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003413 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3414 for (NetworkCallback cb : callbacks) {
3415 mCm.registerNetworkCallback(request, cb);
3416 }
3417 });
3418
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003419 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3420 // Don't request that the network validate, because otherwise connect() will block until
3421 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3422 // and we won't actually measure anything.
3423 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003424
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003425 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003426 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003427 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003428 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3429 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3430 onAvailableDispatchingDuration));
3431 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3432 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3433 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003434
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003435 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003436 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003437 mWiFiNetworkAgent.adjustScore(40);
3438 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003439
3440 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003441 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003442 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003443 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3444 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3445 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3446 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3447 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003448
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003449 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3450 for (NetworkCallback cb : callbacks) {
3451 mCm.unregisterNetworkCallback(cb);
3452 }
3453 });
3454 }
3455
3456 private long durationOf(Runnable fn) {
3457 long startTime = SystemClock.elapsedRealtime();
3458 fn.run();
3459 return SystemClock.elapsedRealtime() - startTime;
3460 }
3461
3462 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3463 long timeTaken = durationOf(fn);
3464 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003465 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003466 assertTrue(msg, timeTaken <= timeLimit);
3467 }
3468
3469 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3470 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09003471 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003472 } catch (InterruptedException e) {}
3473 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003474 }
3475
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003476 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003477 public void testMobileDataAlwaysOn() throws Exception {
3478 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3479 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3480 .addTransportType(TRANSPORT_CELLULAR).build();
3481 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3482
3483 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3484 handlerThread.start();
3485 NetworkCapabilities filter = new NetworkCapabilities()
3486 .addTransportType(TRANSPORT_CELLULAR)
3487 .addCapability(NET_CAPABILITY_INTERNET);
3488 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3489 mServiceContext, "testFactory", filter);
3490 testFactory.setScoreFilter(40);
3491
3492 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003493 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003494 testFactory.register();
3495 testFactory.waitForNetworkRequests(1);
3496 assertTrue(testFactory.getMyStartRequested());
3497
3498 // Bring up wifi. The factory stops looking for a network.
3499 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003500 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3501 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003502 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003503 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003504 assertFalse(testFactory.getMyStartRequested());
3505
3506 ContentResolver cr = mServiceContext.getContentResolver();
3507
3508 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003509 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003510 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003511 testFactory.waitForNetworkRequests(2);
3512 assertTrue(testFactory.getMyStartRequested());
3513
3514 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003515 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003516 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003517 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003518 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003519 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003520 testFactory.waitForNetworkRequests(2);
3521 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3522
3523 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003524 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003525 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003526 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003527
3528 // Turn off mobile data always on and expect the request to disappear...
3529 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003530 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003531 testFactory.waitForNetworkRequests(1);
3532
3533 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003534 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003535 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003536
3537 testFactory.unregister();
3538 mCm.unregisterNetworkCallback(cellNetworkCallback);
3539 handlerThread.quit();
3540 }
3541
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003542 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003543 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003544 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003545 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003546 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3547
Erik Kline065ab6e2016-10-02 18:02:14 +09003548 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003549 String[] values = new String[] {null, "0", "1"};
3550 for (int i = 0; i < values.length; i++) {
3551 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003552 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003553 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003554 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003555 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003556 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003557 }
3558
Erik Kline065ab6e2016-10-02 18:02:14 +09003559 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003560
3561 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003562 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003563 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003564 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003565 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003566
3567 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003568 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003569 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003570 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003571 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003572
3573 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003574 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003575 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003576 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003577 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003578 }
3579
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003580 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003581 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003582 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003583 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003584
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003585 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003586 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003587
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003588 // File a request for cell to ensure it doesn't go down.
3589 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3590 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3591 .addTransportType(TRANSPORT_CELLULAR).build();
3592 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3593
3594 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3595 mCm.registerDefaultNetworkCallback(defaultCallback);
3596
3597 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3598 .addTransportType(TRANSPORT_WIFI)
3599 .addCapability(NET_CAPABILITY_VALIDATED)
3600 .build();
3601 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3602 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3603
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003604 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003605 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003606
3607 // Bring up validated cell.
3608 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3609 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003610 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3611 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003612 Network cellNetwork = mCellNetworkAgent.getNetwork();
3613
3614 // Bring up validated wifi.
3615 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3616 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003617 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3618 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003619 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3620
3621 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003622 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003623 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003624 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003625 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3626
3627 // Because avoid bad wifi is off, we don't switch to cellular.
3628 defaultCallback.assertNoCallback();
3629 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3630 NET_CAPABILITY_VALIDATED));
3631 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3632 NET_CAPABILITY_VALIDATED));
3633 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3634
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003635 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3636 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003637 tracker.configRestrictsAvoidBadWifi = false;
3638 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003639 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003640 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3641
3642 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003643 tracker.configRestrictsAvoidBadWifi = true;
3644 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003645 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003646 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3647
3648 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3649 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003650 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003651 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3652 NET_CAPABILITY_VALIDATED));
3653 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3654 NET_CAPABILITY_VALIDATED));
3655 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3656
3657 // Disconnect and reconnect wifi to clear the one-time switch above.
3658 mWiFiNetworkAgent.disconnect();
3659 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3660 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003661 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3662 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003663 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3664
3665 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003666 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003667 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003668 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003669 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3670
3671 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003672 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003673 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003674
3675 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003676 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003677 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3678 NET_CAPABILITY_VALIDATED));
3679 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3680 NET_CAPABILITY_VALIDATED));
3681 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3682
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003683 // Simulate the user turning the cellular fallback setting off and then on.
3684 // We switch to wifi and then to cell.
3685 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003686 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003687 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003688 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3689 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003690 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003691 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003692 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3693
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003694 // If cell goes down, we switch to wifi.
3695 mCellNetworkAgent.disconnect();
3696 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003697 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003698 validatedWifiCallback.assertNoCallback();
3699
3700 mCm.unregisterNetworkCallback(cellNetworkCallback);
3701 mCm.unregisterNetworkCallback(validatedWifiCallback);
3702 mCm.unregisterNetworkCallback(defaultCallback);
3703 }
3704
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003705 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003706 public void testMeteredMultipathPreferenceSetting() throws Exception {
3707 final ContentResolver cr = mServiceContext.getContentResolver();
3708 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3709 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3710
3711 for (int config : Arrays.asList(0, 3, 2)) {
3712 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3713 tracker.configMeteredMultipathPreference = config;
3714 Settings.Global.putString(cr, settingName, setting);
3715 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003716 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003717
3718 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3719 String msg = String.format("config=%d, setting=%s", config, setting);
3720 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3721 }
3722 }
3723 }
3724
Erik Kline3841a482015-11-25 12:49:38 +09003725 /**
3726 * Validate that a satisfied network request does not trigger onUnavailable() once the
3727 * time-out period expires.
3728 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003729 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003730 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3731 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3732 NetworkCapabilities.TRANSPORT_WIFI).build();
3733 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003734 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003735
3736 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3737 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003738 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003739 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003740
3741 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003742 networkCallback.assertNoCallback();
3743 }
3744
3745 /**
3746 * Validate that a satisfied network request followed by a disconnected (lost) network does
3747 * not trigger onUnavailable() once the time-out period expires.
3748 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003749 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003750 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3751 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3752 NetworkCapabilities.TRANSPORT_WIFI).build();
3753 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003754 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003755
3756 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3757 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003758 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003759 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003760 mWiFiNetworkAgent.disconnect();
3761 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3762
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003763 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003764 networkCallback.assertNoCallback();
3765 }
3766
3767 /**
3768 * Validate that when a time-out is specified for a network request the onUnavailable()
3769 * callback is called when time-out expires. Then validate that if network request is
3770 * (somehow) satisfied - the callback isn't called later.
3771 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003772 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003773 public void testTimedoutNetworkRequest() {
3774 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3775 NetworkCapabilities.TRANSPORT_WIFI).build();
3776 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003777 final int timeoutMs = 10;
3778 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003779
3780 // pass timeout and validate that UNAVAILABLE is called
3781 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3782
3783 // create a network satisfying request - validate that request not triggered
3784 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3785 mWiFiNetworkAgent.connect(false);
3786 networkCallback.assertNoCallback();
3787 }
3788
3789 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003790 * Validate that when a network request is unregistered (cancelled), no posterior event can
3791 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003792 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003793 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003794 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003795 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3796 NetworkCapabilities.TRANSPORT_WIFI).build();
3797 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003798 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003799
Hugo Benichidfb559a2016-12-20 14:57:49 +09003800 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003801 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003802 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3803 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003804 networkCallback.assertNoCallback();
3805
3806 // create a network satisfying request - validate that request not triggered
3807 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3808 mWiFiNetworkAgent.connect(false);
3809 networkCallback.assertNoCallback();
3810 }
3811
Etan Cohenddb720a2019-01-08 12:09:18 -08003812 /**
3813 * Validate the callback flow for a factory releasing a request as unfulfillable.
3814 */
3815 @Test
3816 public void testUnfulfillableNetworkRequest() throws Exception {
3817 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3818 NetworkCapabilities.TRANSPORT_WIFI).build();
3819 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3820
3821 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3822 handlerThread.start();
3823 NetworkCapabilities filter = new NetworkCapabilities()
3824 .addTransportType(TRANSPORT_WIFI)
3825 .addCapability(NET_CAPABILITY_INTERNET);
3826 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3827 mServiceContext, "testFactory", filter);
3828 testFactory.setScoreFilter(40);
3829
3830 // Register the factory and expect it to receive the default request.
Chalard Jean05ab6812018-05-02 21:14:54 +09003831 testFactory.expectAddRequestsWithScores(0); // default request score is 0, not served yet
Etan Cohenddb720a2019-01-08 12:09:18 -08003832 testFactory.register();
3833 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3834
3835 assertEquals(1, requests.size()); // have 1 request at this point
3836 int origRequestId = requests.valueAt(0).requestId;
3837
3838 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003839 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003840 mCm.requestNetwork(nr, networkCallback);
3841 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3842
3843 int newRequestId = 0;
3844 for (int i = 0; i < requests.size(); ++i) {
3845 if (requests.valueAt(i).requestId != origRequestId) {
3846 newRequestId = requests.valueAt(i).requestId;
3847 break;
3848 }
3849 }
3850
3851 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
3852 testFactory.expectRemoveRequests(1);
3853 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3854 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3855 testFactory.waitForRequests();
3856
Etan Cohen9b09a162019-04-16 15:07:55 -07003857 // unregister network callback - a no-op, but should not fail
3858 mCm.unregisterNetworkCallback(networkCallback);
3859
Etan Cohenddb720a2019-01-08 12:09:18 -08003860 testFactory.unregister();
3861 handlerThread.quit();
3862 }
3863
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003864 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3865
3866 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3867
3868 private class CallbackValue {
3869 public CallbackType callbackType;
3870 public int error;
3871
3872 public CallbackValue(CallbackType type) {
3873 this.callbackType = type;
3874 this.error = PacketKeepalive.SUCCESS;
3875 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3876 }
3877
3878 public CallbackValue(CallbackType type, int error) {
3879 this.callbackType = type;
3880 this.error = error;
3881 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3882 }
3883
3884 @Override
3885 public boolean equals(Object o) {
3886 return o instanceof CallbackValue &&
3887 this.callbackType == ((CallbackValue) o).callbackType &&
3888 this.error == ((CallbackValue) o).error;
3889 }
3890
3891 @Override
3892 public String toString() {
3893 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3894 }
3895 }
3896
junyulai7c469172019-01-16 20:23:34 +08003897 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003898
3899 @Override
3900 public void onStarted() {
3901 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3902 }
3903
3904 @Override
3905 public void onStopped() {
3906 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3907 }
3908
3909 @Override
3910 public void onError(int error) {
3911 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3912 }
3913
3914 private void expectCallback(CallbackValue callbackValue) {
3915 try {
3916 assertEquals(
3917 callbackValue,
3918 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3919 } catch (InterruptedException e) {
3920 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3921 }
3922 }
3923
3924 public void expectStarted() {
3925 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3926 }
3927
3928 public void expectStopped() {
3929 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3930 }
3931
3932 public void expectError(int error) {
3933 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3934 }
3935 }
3936
junyulai48eac1d42018-12-27 17:25:29 +08003937 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3938
3939 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3940
3941 private class CallbackValue {
3942 public CallbackType callbackType;
3943 public int error;
3944
3945 CallbackValue(CallbackType type) {
3946 this.callbackType = type;
3947 this.error = SocketKeepalive.SUCCESS;
3948 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3949 }
3950
3951 CallbackValue(CallbackType type, int error) {
3952 this.callbackType = type;
3953 this.error = error;
3954 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3955 }
3956
3957 @Override
3958 public boolean equals(Object o) {
3959 return o instanceof CallbackValue
3960 && this.callbackType == ((CallbackValue) o).callbackType
3961 && this.error == ((CallbackValue) o).error;
3962 }
3963
3964 @Override
3965 public String toString() {
3966 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3967 error);
3968 }
3969 }
3970
3971 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003972 private final Executor mExecutor;
3973
3974 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3975 mExecutor = executor;
3976 }
junyulai48eac1d42018-12-27 17:25:29 +08003977
3978 @Override
3979 public void onStarted() {
3980 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3981 }
3982
3983 @Override
3984 public void onStopped() {
3985 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3986 }
3987
3988 @Override
3989 public void onError(int error) {
3990 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3991 }
3992
3993 private void expectCallback(CallbackValue callbackValue) {
3994 try {
3995 assertEquals(
3996 callbackValue,
3997 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3998 } catch (InterruptedException e) {
3999 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
4000 }
4001 }
4002
4003 public void expectStarted() {
4004 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4005 }
4006
4007 public void expectStopped() {
4008 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4009 }
4010
4011 public void expectError(int error) {
4012 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4013 }
junyulai7c469172019-01-16 20:23:34 +08004014
4015 public void assertNoCallback() {
4016 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
4017 CallbackValue cv = mCallbacks.peek();
4018 assertNull("Unexpected callback: " + cv, cv);
4019 }
junyulai48eac1d42018-12-27 17:25:29 +08004020 }
4021
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004022 private Network connectKeepaliveNetwork(LinkProperties lp) {
4023 // Ensure the network is disconnected before we do anything.
4024 if (mWiFiNetworkAgent != null) {
4025 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
4026 }
4027
4028 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4029 ConditionVariable cv = waitForConnectivityBroadcasts(1);
4030 mWiFiNetworkAgent.connect(true);
4031 waitFor(cv);
4032 verifyActiveNetwork(TRANSPORT_WIFI);
4033 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09004034 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004035 return mWiFiNetworkAgent.getNetwork();
4036 }
4037
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004038 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004039 public void testPacketKeepalives() throws Exception {
4040 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4041 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4042 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4043 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4044 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4045
Nathan Harold63dd8132018-02-14 13:09:45 -08004046 final int validKaInterval = 15;
4047 final int invalidKaInterval = 9;
4048
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004049 LinkProperties lp = new LinkProperties();
4050 lp.setInterfaceName("wlan12");
4051 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4052 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4053 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4054 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4055
4056 Network notMyNet = new Network(61234);
4057 Network myNet = connectKeepaliveNetwork(lp);
4058
4059 TestKeepaliveCallback callback = new TestKeepaliveCallback();
4060 PacketKeepalive ka;
4061
4062 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08004063 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004064 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4065
Nathan Harold63dd8132018-02-14 13:09:45 -08004066 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004067 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4068
Nathan Harold63dd8132018-02-14 13:09:45 -08004069 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004070 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4071
Nathan Harold63dd8132018-02-14 13:09:45 -08004072 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004073 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4074
Nathan Harold63dd8132018-02-14 13:09:45 -08004075 // NAT-T is only supported for IPv4.
4076 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4077 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004078
Nathan Harold63dd8132018-02-14 13:09:45 -08004079 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004080 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4081
Nathan Harold63dd8132018-02-14 13:09:45 -08004082 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004083 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4084
Nathan Harold63dd8132018-02-14 13:09:45 -08004085 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004086 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4087
Nathan Harold63dd8132018-02-14 13:09:45 -08004088 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004089 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4090
4091 // Check that a started keepalive can be stopped.
4092 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08004093 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004094 callback.expectStarted();
4095 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
4096 ka.stop();
4097 callback.expectStopped();
4098
4099 // Check that deleting the IP address stops the keepalive.
4100 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08004101 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004102 callback.expectStarted();
4103 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4104 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4105 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4106 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4107 mWiFiNetworkAgent.sendLinkProperties(lp);
4108
4109 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004110 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004111 callback.expectStarted();
4112 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004113 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004114 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4115
4116 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004117 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004118 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004119 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004120 ka.stop();
4121
4122 // Reconnect.
4123 myNet = connectKeepaliveNetwork(lp);
4124 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
4125
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004126 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4127 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004128 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004129 callback.expectStarted();
4130
4131 // The second one gets slot 2.
4132 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4133 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004134 PacketKeepalive ka2 = mCm.startNattKeepalive(
4135 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004136 callback2.expectStarted();
4137
4138 // Now stop the first one and create a third. This also gets slot 1.
4139 ka.stop();
4140 callback.expectStopped();
4141
4142 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4143 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004144 PacketKeepalive ka3 = mCm.startNattKeepalive(
4145 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004146 callback3.expectStarted();
4147
4148 ka2.stop();
4149 callback2.expectStopped();
4150
4151 ka3.stop();
4152 callback3.expectStopped();
4153 }
Udam Sainib7c24872016-01-04 12:16:14 -08004154
junyulaiafe9b492019-03-19 18:50:23 +08004155 @FunctionalInterface
4156 private interface ThrowingConsumer<T> {
4157 void accept(T t) throws Exception;
4158 }
4159
Xiao Maa4637112019-02-07 15:03:57 +09004160 // Helper method to prepare the executor and run test
junyulaiafe9b492019-03-19 18:50:23 +08004161 private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
junyulai06835112019-01-03 18:50:15 +08004162 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004163 final Executor executorInline = (Runnable r) -> r.run();
4164 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08004165 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004166 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004167 }
junyulai06835112019-01-03 18:50:15 +08004168
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004169 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004170 public void testNattSocketKeepalives() throws Exception {
4171 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4172 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08004173 }
4174
4175 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004176 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08004177 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004178 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004179 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4180 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4181 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4182 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4183 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4184
4185 final int validKaInterval = 15;
4186 final int invalidKaInterval = 9;
4187
4188 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004189 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4190 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004191
junyulai48eac1d42018-12-27 17:25:29 +08004192 LinkProperties lp = new LinkProperties();
4193 lp.setInterfaceName("wlan12");
4194 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4195 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4196 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4197 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4198
4199 Network notMyNet = new Network(61234);
4200 Network myNet = connectKeepaliveNetwork(lp);
4201
junyulai7c469172019-01-16 20:23:34 +08004202 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004203
4204 // Attempt to start keepalives with invalid parameters and check for errors.
4205 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004206 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4207 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4208 ka.start(validKaInterval);
4209 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4210 }
junyulai48eac1d42018-12-27 17:25:29 +08004211
4212 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004213 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4214 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4215 ka.start(invalidKaInterval);
4216 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4217 }
junyulai48eac1d42018-12-27 17:25:29 +08004218
4219 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004220 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4221 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4222 ka.start(validKaInterval);
4223 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4224 }
junyulai48eac1d42018-12-27 17:25:29 +08004225
4226 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004227 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4228 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4229 ka.start(validKaInterval);
4230 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4231 }
junyulai48eac1d42018-12-27 17:25:29 +08004232
4233 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004234 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4235 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4236 ka.start(validKaInterval);
4237 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4238 }
junyulai48eac1d42018-12-27 17:25:29 +08004239
4240 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004241 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4242 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4243 ka.start(validKaInterval);
4244 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4245 }
junyulai48eac1d42018-12-27 17:25:29 +08004246
4247 // Check that a started keepalive can be stopped.
4248 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004249 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4250 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4251 ka.start(validKaInterval);
4252 callback.expectStarted();
4253 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4254 ka.stop();
4255 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004256
junyulai0c666972019-03-04 22:45:36 +08004257 // Check that keepalive could be restarted.
4258 ka.start(validKaInterval);
4259 callback.expectStarted();
4260 ka.stop();
4261 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004262
junyulai0c666972019-03-04 22:45:36 +08004263 // Check that keepalive can be restarted without waiting for callback.
4264 ka.start(validKaInterval);
4265 callback.expectStarted();
4266 ka.stop();
4267 ka.start(validKaInterval);
4268 callback.expectStopped();
4269 callback.expectStarted();
4270 ka.stop();
4271 callback.expectStopped();
junyulaicecd4a32019-04-16 19:32:32 +08004272
4273 // Check that the same NATT socket cannot be used by 2 keepalives.
4274 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4275 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4276 // Check that second keepalive cannot be started if the first one is running.
4277 ka.start(validKaInterval);
4278 callback.expectStarted();
4279 ka2.start(validKaInterval);
4280 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4281 ka.stop();
4282 callback.expectStopped();
4283
4284 // Check that second keepalive can be started/stopped normally if the first one is
4285 // stopped.
4286 ka2.start(validKaInterval);
4287 callback.expectStarted();
4288 ka2.stop();
4289 callback.expectStopped();
4290 }
junyulai0c666972019-03-04 22:45:36 +08004291 }
junyulai7c469172019-01-16 20:23:34 +08004292
junyulai48eac1d42018-12-27 17:25:29 +08004293 // Check that deleting the IP address stops the keepalive.
4294 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004295 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4296 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4297 ka.start(validKaInterval);
4298 callback.expectStarted();
4299 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4300 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4301 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4302 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4303 mWiFiNetworkAgent.sendLinkProperties(lp);
4304 }
junyulai48eac1d42018-12-27 17:25:29 +08004305
4306 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004307 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4308 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4309 ka.start(validKaInterval);
4310 callback.expectStarted();
4311 mWiFiNetworkAgent.disconnect();
4312 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4313 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004314
junyulai0c666972019-03-04 22:45:36 +08004315 // ... and that stopping it after that has no adverse effects.
4316 waitForIdle();
4317 final Network myNetAlias = myNet;
4318 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4319 ka.stop();
4320 callback.assertNoCallback();
4321 }
junyulai48eac1d42018-12-27 17:25:29 +08004322
4323 // Reconnect.
4324 myNet = connectKeepaliveNetwork(lp);
4325 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4326
4327 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4328 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004329 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004330 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4331 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4332 ka.start(validKaInterval);
4333 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004334
junyulai0c666972019-03-04 22:45:36 +08004335 // The second one gets slot 2.
4336 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004337 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4338 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004339 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4340 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4341 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4342 ka2.start(validKaInterval);
4343 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004344
junyulai0c666972019-03-04 22:45:36 +08004345 ka.stop();
4346 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004347
junyulai0c666972019-03-04 22:45:36 +08004348 ka2.stop();
4349 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004350
junyulai0c666972019-03-04 22:45:36 +08004351 testSocket.close();
4352 testSocket2.close();
4353 }
junyulaicecd4a32019-04-16 19:32:32 +08004354
4355 // Check that the closed socket cannot be used to start keepalive.
4356 ka.start(validKaInterval);
4357 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
junyulai0c666972019-03-04 22:45:36 +08004358 }
junyulai06835112019-01-03 18:50:15 +08004359
junyulai15178152019-03-27 11:00:37 +08004360 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004361 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4362 // assertFalse(isUdpPortInUse(srcPort));
4363 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004364
junyulai06835112019-01-03 18:50:15 +08004365 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004366 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Xiao Maa4637112019-02-07 15:03:57 +09004367 mWiFiNetworkAgent = null;
4368 }
4369
4370 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004371 public void testTcpSocketKeepalives() throws Exception {
4372 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004373 }
4374
4375 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4376 final int srcPortV4 = 12345;
4377 final int srcPortV6 = 23456;
4378 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4379 final InetAddress myIPv6 = InetAddress.getByName("::1");
4380
4381 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004382
4383 final LinkProperties lp = new LinkProperties();
4384 lp.setInterfaceName("wlan12");
4385 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4386 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4387 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4388 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4389
4390 final Network notMyNet = new Network(61234);
4391 final Network myNet = connectKeepaliveNetwork(lp);
4392
4393 final Socket testSocketV4 = new Socket();
4394 final Socket testSocketV6 = new Socket();
4395
junyulai7c469172019-01-16 20:23:34 +08004396 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004397
4398 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4399 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004400 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4401 notMyNet, testSocketV4, executor, callback)) {
4402 ka.start(validKaInterval);
4403 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4404 }
Xiao Maa4637112019-02-07 15:03:57 +09004405
4406 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004407 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4408 myNet, testSocketV4, executor, callback)) {
4409 ka.start(validKaInterval);
4410 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4411 }
Xiao Maa4637112019-02-07 15:03:57 +09004412
4413 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004414 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4415 myNet, testSocketV6, executor, callback)) {
4416 ka.start(validKaInterval);
4417 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4418 }
Xiao Maa4637112019-02-07 15:03:57 +09004419
4420 // Bind the socket address
4421 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4422 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4423
4424 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004425 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4426 myNet, testSocketV4, executor, callback)) {
4427 ka.start(validKaInterval);
4428 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4429 }
Xiao Maa4637112019-02-07 15:03:57 +09004430
4431 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004432 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4433 myNet, testSocketV6, executor, callback)) {
4434 ka.start(validKaInterval);
4435 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4436 }
Xiao Maa4637112019-02-07 15:03:57 +09004437
4438 testSocketV4.close();
4439 testSocketV6.close();
4440
4441 mWiFiNetworkAgent.disconnect();
4442 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4443 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004444 }
4445
junyulai0c666972019-03-04 22:45:36 +08004446 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004447 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4448 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4449 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4450 final int validKaInterval = 15;
4451
4452 // Prepare the target network.
4453 LinkProperties lp = new LinkProperties();
4454 lp.setInterfaceName("wlan12");
4455 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4456 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4457 Network myNet = connectKeepaliveNetwork(lp);
4458 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4459 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4460
4461 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4462
4463 // Prepare the target file descriptor, keep only one instance.
4464 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004465 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4466 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004467 final ParcelFileDescriptor testPfd =
4468 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4469 testSocket.close();
4470 assertTrue(isUdpPortInUse(srcPort));
4471
4472 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4473 // block.
4474 try (SocketKeepalive ka = mCm.createNattKeepalive(
4475 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4476 ka.start(validKaInterval);
4477 callback.expectStarted();
4478 ka.stop();
4479 callback.expectStopped();
4480 }
4481
4482 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4483 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4484 // address.
4485 assertTrue(isUdpPortInUse(srcPort));
4486 final InetSocketAddress sa =
4487 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4488 assertEquals(anyIPv4, sa.getAddress());
4489
4490 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004491 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4492 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004493
4494 mWiFiNetworkAgent.disconnect();
4495 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4496 mWiFiNetworkAgent = null;
4497 }
4498
4499 private static boolean isUdpPortInUse(int port) {
4500 try (DatagramSocket ignored = new DatagramSocket(port)) {
4501 return false;
4502 } catch (IOException ignored) {
4503 return true;
4504 }
4505 }
4506
junyulai48eac1d42018-12-27 17:25:29 +08004507 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004508 public void testGetCaptivePortalServerUrl() throws Exception {
4509 String url = mCm.getCaptivePortalServerUrl();
4510 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4511 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004512
4513 private static class TestNetworkPinner extends NetworkPinner {
4514 public static boolean awaitPin(int timeoutMs) {
4515 synchronized(sLock) {
4516 if (sNetwork == null) {
4517 try {
4518 sLock.wait(timeoutMs);
4519 } catch (InterruptedException e) {}
4520 }
4521 return sNetwork != null;
4522 }
4523 }
4524
4525 public static boolean awaitUnpin(int timeoutMs) {
4526 synchronized(sLock) {
4527 if (sNetwork != null) {
4528 try {
4529 sLock.wait(timeoutMs);
4530 } catch (InterruptedException e) {}
4531 }
4532 return sNetwork == null;
4533 }
4534 }
4535 }
4536
4537 private void assertPinnedToWifiWithCellDefault() {
4538 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4539 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4540 }
4541
4542 private void assertPinnedToWifiWithWifiDefault() {
4543 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4544 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4545 }
4546
4547 private void assertNotPinnedToWifi() {
4548 assertNull(mCm.getBoundNetworkForProcess());
4549 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4550 }
4551
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004552 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004553 public void testNetworkPinner() {
4554 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4555 .addTransportType(TRANSPORT_WIFI)
4556 .build();
4557 assertNull(mCm.getBoundNetworkForProcess());
4558
4559 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4560 assertNull(mCm.getBoundNetworkForProcess());
4561
4562 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4563 mCellNetworkAgent.connect(true);
4564 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4565 mWiFiNetworkAgent.connect(false);
4566
4567 // When wi-fi connects, expect to be pinned.
4568 assertTrue(TestNetworkPinner.awaitPin(100));
4569 assertPinnedToWifiWithCellDefault();
4570
4571 // Disconnect and expect the pin to drop.
4572 mWiFiNetworkAgent.disconnect();
4573 assertTrue(TestNetworkPinner.awaitUnpin(100));
4574 assertNotPinnedToWifi();
4575
4576 // Reconnecting does not cause the pin to come back.
4577 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4578 mWiFiNetworkAgent.connect(false);
4579 assertFalse(TestNetworkPinner.awaitPin(100));
4580 assertNotPinnedToWifi();
4581
4582 // Pinning while connected causes the pin to take effect immediately.
4583 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4584 assertTrue(TestNetworkPinner.awaitPin(100));
4585 assertPinnedToWifiWithCellDefault();
4586
4587 // Explicitly unpin and expect to use the default network again.
4588 TestNetworkPinner.unpin();
4589 assertNotPinnedToWifi();
4590
4591 // Disconnect cell and wifi.
4592 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4593 mCellNetworkAgent.disconnect();
4594 mWiFiNetworkAgent.disconnect();
4595 waitFor(cv);
4596
4597 // Pinning takes effect even if the pinned network is the default when the pin is set...
4598 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4599 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4600 mWiFiNetworkAgent.connect(false);
4601 assertTrue(TestNetworkPinner.awaitPin(100));
4602 assertPinnedToWifiWithWifiDefault();
4603
4604 // ... and is maintained even when that network is no longer the default.
4605 cv = waitForConnectivityBroadcasts(1);
4606 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4607 mCellNetworkAgent.connect(true);
4608 waitFor(cv);
4609 assertPinnedToWifiWithCellDefault();
4610 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004611
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004612 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004613 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004614 // We can only have 99 callbacks, because MultipathPolicyTracker is
4615 // already one of them.
4616 final int MAX_REQUESTS = 99;
4617 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004618 final int INTENTS = 10;
4619 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4620
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004621 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004622 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004623
Hugo Benichi893a7622017-09-29 09:34:08 +09004624 int j = 0;
4625 while (j++ < CALLBACKS / 2) {
4626 NetworkCallback cb = new NetworkCallback();
4627 mCm.requestNetwork(networkRequest, cb);
4628 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004629 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004630 while (j++ < CALLBACKS) {
4631 NetworkCallback cb = new NetworkCallback();
4632 mCm.registerNetworkCallback(networkRequest, cb);
4633 registered.add(cb);
4634 }
4635 j = 0;
4636 while (j++ < INTENTS / 2) {
4637 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4638 mCm.requestNetwork(networkRequest, pi);
4639 registered.add(pi);
4640 }
4641 while (j++ < INTENTS) {
4642 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4643 mCm.registerNetworkCallback(networkRequest, pi);
4644 registered.add(pi);
4645 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004646
Hugo Benichi893a7622017-09-29 09:34:08 +09004647 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004648 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09004649 mCm.requestNetwork(networkRequest, new NetworkCallback());
4650 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09004651 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09004652 try {
4653 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4654 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4655 } catch (TooManyRequestsException expected) {}
4656 try {
4657 mCm.requestNetwork(networkRequest,
4658 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4659 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4660 } catch (TooManyRequestsException expected) {}
4661 try {
4662 mCm.registerNetworkCallback(networkRequest,
4663 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4664 fail("Registering " + MAX_REQUESTS
4665 + " PendingIntent callbacks did not throw exception");
4666 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004667
Hugo Benichi893a7622017-09-29 09:34:08 +09004668 for (Object o : registered) {
4669 if (o instanceof NetworkCallback) {
4670 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004671 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004672 if (o instanceof PendingIntent) {
4673 mCm.unregisterNetworkCallback((PendingIntent)o);
4674 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004675 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004676 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004677
4678 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4679 for (int i = 0; i < MAX_REQUESTS; i++) {
4680 NetworkCallback networkCallback = new NetworkCallback();
4681 mCm.requestNetwork(networkRequest, networkCallback);
4682 mCm.unregisterNetworkCallback(networkCallback);
4683 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004684 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004685
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004686 for (int i = 0; i < MAX_REQUESTS; i++) {
4687 NetworkCallback networkCallback = new NetworkCallback();
4688 mCm.registerNetworkCallback(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 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004695 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004696 mCm.requestNetwork(networkRequest, pendingIntent);
4697 mCm.unregisterNetworkCallback(pendingIntent);
4698 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004699 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004700
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004701 for (int i = 0; i < MAX_REQUESTS; i++) {
4702 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004703 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004704 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4705 mCm.unregisterNetworkCallback(pendingIntent);
4706 }
4707 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004708
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004709 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004710 public void testNetworkInfoOfTypeNone() {
4711 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4712
4713 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09004714 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004715 assertNull(mCm.getActiveNetworkInfo());
4716
4717 Network[] allNetworks = mCm.getAllNetworks();
4718 assertLength(1, allNetworks);
4719 Network network = allNetworks[0];
4720 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4721 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4722
4723 final NetworkRequest request =
4724 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4725 final TestNetworkCallback callback = new TestNetworkCallback();
4726 mCm.registerNetworkCallback(request, callback);
4727
Hugo Benichic1014502017-07-19 10:10:52 +09004728 // Bring up wifi aware network.
4729 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004730 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004731
4732 assertNull(mCm.getActiveNetworkInfo());
4733 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004734 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004735 // of this test. Fix it and uncomment the assert below.
4736 //assertEmpty(mCm.getAllNetworkInfo());
4737
Hugo Benichic1014502017-07-19 10:10:52 +09004738 // Disconnect wifi aware network.
4739 wifiAware.disconnect();
4740 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004741 mCm.unregisterNetworkCallback(callback);
4742
4743 verifyNoNetwork();
4744 if (broadcastCV.block(10)) {
4745 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4746 }
4747 }
4748
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004749 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004750 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4751 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4752 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4753 assertNull(mCm.getNetworkForType(TYPE_NONE));
4754 assertNull(mCm.getLinkProperties(TYPE_NONE));
4755 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4756
4757 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4758 IllegalArgumentException.class);
4759
4760 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4761 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4762 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4763 // TODO: let test context have configuration application target sdk version
4764 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4765 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4766 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4767 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4768 }
4769
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004770 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01004771 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4772 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4773 .addTransportType(TRANSPORT_WIFI).build();
4774 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4775 mCm.registerNetworkCallback(networkRequest, networkCallback);
4776
4777 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004778 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004779 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4780 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4781 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4782 lp.addLinkAddress(myIpv4Address);
4783 lp.addRoute(myIpv4DefaultRoute);
4784
4785 // Verify direct routes are added when network agent is first registered in
4786 // ConnectivityService.
4787 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4788 networkAgent.connect(true);
4789 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4790 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4791 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4792 networkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004793 networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004794 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4795 networkCallback.assertNoCallback();
4796 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4797 Arrays.asList(myIpv4DefaultRoute));
4798 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4799 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4800
4801 // Verify direct routes are added during subsequent link properties updates.
4802 LinkProperties newLp = new LinkProperties(lp);
4803 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4804 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4805 newLp.addLinkAddress(myIpv6Address1);
4806 newLp.addLinkAddress(myIpv6Address2);
4807 networkAgent.sendLinkProperties(newLp);
4808 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4809 networkCallback.assertNoCallback();
4810 checkDirectlyConnectedRoutes(cbi.arg,
4811 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4812 Arrays.asList(myIpv4DefaultRoute));
4813 mCm.unregisterNetworkCallback(networkCallback);
4814 }
4815
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004816 @Test
4817 public void testStatsIfacesChanged() throws Exception {
4818 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004819 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4820
Varun Anandd33cbc62019-02-07 14:13:13 -08004821 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4822 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4823
4824 LinkProperties cellLp = new LinkProperties();
4825 cellLp.setInterfaceName(MOBILE_IFNAME);
4826 LinkProperties wifiLp = new LinkProperties();
4827 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004828
4829 // Simple connection should have updated ifaces
4830 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004831 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004832 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004833 verify(mStatsService, atLeastOnce())
4834 .forceUpdateIfaces(
4835 eq(onlyCell),
4836 eq(new VpnInfo[0]),
4837 any(NetworkState[].class),
4838 eq(MOBILE_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004839 reset(mStatsService);
4840
4841 // Default network switch should update ifaces.
4842 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004843 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004844 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004845 assertEquals(wifiLp, mService.getActiveLinkProperties());
4846 verify(mStatsService, atLeastOnce())
4847 .forceUpdateIfaces(
4848 eq(onlyWifi),
4849 eq(new VpnInfo[0]),
4850 any(NetworkState[].class),
4851 eq(WIFI_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004852 reset(mStatsService);
4853
4854 // Disconnect should update ifaces.
4855 mWiFiNetworkAgent.disconnect();
4856 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004857 verify(mStatsService, atLeastOnce())
4858 .forceUpdateIfaces(
4859 eq(onlyCell),
4860 eq(new VpnInfo[0]),
4861 any(NetworkState[].class),
4862 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004863 reset(mStatsService);
4864
4865 // Metered change should update ifaces
4866 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4867 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004868 verify(mStatsService, atLeastOnce())
4869 .forceUpdateIfaces(
4870 eq(onlyCell),
4871 eq(new VpnInfo[0]),
4872 any(NetworkState[].class),
4873 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004874 reset(mStatsService);
4875
4876 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4877 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004878 verify(mStatsService, atLeastOnce())
4879 .forceUpdateIfaces(
4880 eq(onlyCell),
4881 eq(new VpnInfo[0]),
4882 any(NetworkState[].class),
4883 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004884 reset(mStatsService);
4885
4886 // Captive portal change shouldn't update ifaces
4887 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4888 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004889 verify(mStatsService, never())
4890 .forceUpdateIfaces(
4891 eq(onlyCell),
4892 eq(new VpnInfo[0]),
4893 any(NetworkState[].class),
4894 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004895 reset(mStatsService);
4896
4897 // Roaming change should update ifaces
4898 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4899 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004900 verify(mStatsService, atLeastOnce())
4901 .forceUpdateIfaces(
4902 eq(onlyCell),
4903 eq(new VpnInfo[0]),
4904 any(NetworkState[].class),
4905 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004906 reset(mStatsService);
4907 }
4908
Erik Klinee89953b2018-01-11 16:11:10 +09004909 @Test
4910 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004911 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004912
4913 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004914 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004915
Erik Klinee89953b2018-01-11 16:11:10 +09004916 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4917 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004918 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004919 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004920
4921 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004922 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004923 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4924 // "is-reachable" testing in order to not program netd with unreachable
4925 // nameservers that it might try repeated to validate.
4926 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004927 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4928 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004929 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004930 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4931 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004932 mCellNetworkAgent.sendLinkProperties(cellLp);
4933 mCellNetworkAgent.connect(false);
4934 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004935
4936 verify(mMockDnsResolver, times(1)).createNetworkCache(
4937 eq(mCellNetworkAgent.getNetwork().netId));
4938 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004939 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004940 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004941
4942 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4943 mCellNetworkAgent.sendLinkProperties(cellLp);
4944 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004945 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004946 mResolverParamsParcelCaptor.capture());
4947 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4948 assertEquals(1, resolvrParams.servers.length);
4949 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004950 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004951 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004952 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004953
4954 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4955 mCellNetworkAgent.sendLinkProperties(cellLp);
4956 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004957 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004958 mResolverParamsParcelCaptor.capture());
4959 resolvrParams = mResolverParamsParcelCaptor.getValue();
4960 assertEquals(2, resolvrParams.servers.length);
4961 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004962 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004963 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004964 assertEquals(2, resolvrParams.tlsServers.length);
4965 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004966 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004967 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004968
4969 final String TLS_SPECIFIER = "tls.example.com";
4970 final String TLS_SERVER6 = "2001:db8:53::53";
4971 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4972 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004973 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4974 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4975
Erik Kline117e7f32018-03-04 21:01:01 +09004976 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004977 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004978 mResolverParamsParcelCaptor.capture());
4979 resolvrParams = mResolverParamsParcelCaptor.getValue();
4980 assertEquals(2, resolvrParams.servers.length);
4981 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004982 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004983 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004984 }
4985
Erik Kline79c6d052018-03-21 07:18:33 -07004986 @Test
4987 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004988 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004989 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004990
4991 // The default on Android is opportunistic mode ("Automatic").
4992 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4993
dalyk1fcb7392018-03-05 12:42:22 -05004994 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4995 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4996 .addTransportType(TRANSPORT_CELLULAR).build();
4997 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4998
Erik Kline79c6d052018-03-21 07:18:33 -07004999 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5000 waitForIdle();
5001 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08005002 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005003 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005004
5005 final LinkProperties cellLp = new LinkProperties();
5006 cellLp.setInterfaceName(MOBILE_IFNAME);
5007 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5008 // "is-reachable" testing in order to not program netd with unreachable
5009 // nameservers that it might try repeated to validate.
5010 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
5011 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5012 MOBILE_IFNAME));
5013 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
5014 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5015 MOBILE_IFNAME));
5016 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5017 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5018
5019 mCellNetworkAgent.sendLinkProperties(cellLp);
5020 mCellNetworkAgent.connect(false);
5021 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005022 verify(mMockDnsResolver, times(1)).createNetworkCache(
5023 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08005024 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005025 mResolverParamsParcelCaptor.capture());
5026 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5027 assertEquals(2, resolvrParams.tlsServers.length);
5028 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005029 new String[]{"2001:db8::1", "192.0.2.1"}));
5030 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08005031 assertEquals(2, resolvrParams.tlsServers.length);
5032 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005033 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005034 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005035 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5036 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5037 mCellNetworkAgent);
5038 CallbackInfo cbi = cellNetworkCallback.expectCallback(
5039 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005040 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005041 cellNetworkCallback.assertNoCallback();
5042 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5043 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07005044
5045 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005046 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005047 mResolverParamsParcelCaptor.capture());
5048 resolvrParams = mResolverParamsParcelCaptor.getValue();
5049 assertEquals(2, resolvrParams.servers.length);
5050 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline79c6d052018-03-21 07:18:33 -07005051 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005052 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005053 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005054
5055 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005056 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005057 mResolverParamsParcelCaptor.capture());
5058 resolvrParams = mResolverParamsParcelCaptor.getValue();
5059 assertEquals(2, resolvrParams.servers.length);
5060 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline79c6d052018-03-21 07:18:33 -07005061 new String[]{"2001:db8::1", "192.0.2.1"}));
waynema13516842019-03-12 18:13:49 +08005062 assertEquals(2, resolvrParams.tlsServers.length);
5063 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005064 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005065 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005066 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005067
dalyk1fcb7392018-03-05 12:42:22 -05005068 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5069 // Can't test dns configuration for strict mode without properly mocking
5070 // out the DNS lookups, but can test that LinkProperties is updated.
5071 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5072 mCellNetworkAgent);
5073 cellNetworkCallback.assertNoCallback();
5074 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5075 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
5076 }
5077
5078 @Test
5079 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5080 // The default on Android is opportunistic mode ("Automatic").
5081 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5082
5083 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5084 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5085 .addTransportType(TRANSPORT_CELLULAR).build();
5086 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5087
5088 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5089 waitForIdle();
5090 LinkProperties lp = new LinkProperties();
5091 mCellNetworkAgent.sendLinkProperties(lp);
5092 mCellNetworkAgent.connect(false);
5093 waitForIdle();
5094 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5095 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5096 mCellNetworkAgent);
5097 CallbackInfo cbi = cellNetworkCallback.expectCallback(
5098 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005099 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005100 cellNetworkCallback.assertNoCallback();
5101 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5102 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5103 Set<InetAddress> dnsServers = new HashSet<>();
5104 checkDnsServers(cbi.arg, dnsServers);
5105
5106 // Send a validation event for a server that is not part of the current
5107 // resolver config. The validation event should be ignored.
5108 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5109 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5110 cellNetworkCallback.assertNoCallback();
5111
5112 // Add a dns server to the LinkProperties.
5113 LinkProperties lp2 = new LinkProperties(lp);
5114 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5115 mCellNetworkAgent.sendLinkProperties(lp2);
5116 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5117 mCellNetworkAgent);
5118 cellNetworkCallback.assertNoCallback();
5119 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5120 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5121 dnsServers.add(InetAddress.getByName("145.100.185.16"));
5122 checkDnsServers(cbi.arg, dnsServers);
5123
5124 // Send a validation event containing a hostname that is not part of
5125 // the current resolver config. The validation event should be ignored.
5126 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5127 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5128 cellNetworkCallback.assertNoCallback();
5129
5130 // Send a validation event where validation failed.
5131 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5132 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5133 cellNetworkCallback.assertNoCallback();
5134
5135 // Send a validation event where validation succeeded for a server in
5136 // the current resolver config. A LinkProperties callback with updated
5137 // private dns fields should be sent.
5138 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5139 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
5140 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5141 mCellNetworkAgent);
5142 cellNetworkCallback.assertNoCallback();
5143 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5144 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5145 checkDnsServers(cbi.arg, dnsServers);
5146
5147 // The private dns fields in LinkProperties should be preserved when
5148 // the network agent sends unrelated changes.
5149 LinkProperties lp3 = new LinkProperties(lp2);
5150 lp3.setMtu(1300);
5151 mCellNetworkAgent.sendLinkProperties(lp3);
5152 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5153 mCellNetworkAgent);
5154 cellNetworkCallback.assertNoCallback();
5155 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5156 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5157 checkDnsServers(cbi.arg, dnsServers);
5158 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
5159
5160 // Removing the only validated server should affect the private dns
5161 // fields in LinkProperties.
5162 LinkProperties lp4 = new LinkProperties(lp3);
5163 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5164 mCellNetworkAgent.sendLinkProperties(lp4);
5165 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5166 mCellNetworkAgent);
5167 cellNetworkCallback.assertNoCallback();
5168 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5169 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5170 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
5171 checkDnsServers(cbi.arg, dnsServers);
5172 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005173 }
5174
Rubin Xu1bb5c082017-09-05 18:40:49 +01005175 private void checkDirectlyConnectedRoutes(Object callbackObj,
5176 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5177 assertTrue(callbackObj instanceof LinkProperties);
5178 LinkProperties lp = (LinkProperties) callbackObj;
5179
5180 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5181 expectedRoutes.addAll(otherRoutes);
5182 for (LinkAddress address : linkAddresses) {
5183 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5184 // Duplicates in linkAddresses are considered failures
5185 assertTrue(expectedRoutes.add(localRoute));
5186 }
5187 List<RouteInfo> observedRoutes = lp.getRoutes();
5188 assertEquals(expectedRoutes.size(), observedRoutes.size());
5189 assertTrue(observedRoutes.containsAll(expectedRoutes));
5190 }
5191
dalyk1fcb7392018-03-05 12:42:22 -05005192 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5193 assertTrue(callbackObj instanceof LinkProperties);
5194 LinkProperties lp = (LinkProperties) callbackObj;
5195 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5196 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5197 }
5198
Hugo Benichifed512a2017-06-26 10:06:49 +09005199 private static <T> void assertEmpty(T[] ts) {
5200 int length = ts.length;
5201 assertEquals("expected empty array, but length was " + length, 0, length);
5202 }
5203
5204 private static <T> void assertLength(int expected, T[] got) {
5205 int length = got.length;
5206 assertEquals(String.format("expected array of length %s, but length was %s for %s",
5207 expected, length, Arrays.toString(got)), expected, length);
5208 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09005209
5210 private static <T> void assertException(Runnable block, Class<T> expected) {
5211 try {
5212 block.run();
5213 fail("Expected exception of type " + expected);
5214 } catch (Exception got) {
5215 if (!got.getClass().equals(expected)) {
5216 fail("Expected exception of type " + expected + " but got " + got);
5217 }
5218 return;
5219 }
5220 }
Chalard Jean0b214af2018-01-12 17:22:49 +09005221
5222 @Test
5223 public void testVpnNetworkActive() {
5224 final int uid = Process.myUid();
5225
5226 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005227 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005228 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5229 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005230 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005231 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5232 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5233 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005234 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5235 .addTransportType(TRANSPORT_WIFI).build();
5236 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005237 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005238 .addTransportType(TRANSPORT_VPN).build();
5239 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005240 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005241 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5242 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005243 mCm.registerDefaultNetworkCallback(defaultCallback);
5244 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005245
5246 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5247 mWiFiNetworkAgent.connect(false);
5248
5249 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005250 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005251 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005252 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005253 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005254 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005255
5256 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5257 final ArraySet<UidRange> ranges = new ArraySet<>();
5258 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005259 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5260 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005261 // VPN networks do not satisfy the default request and are automatically validated
5262 // by NetworkMonitor
Lorenzo Colittied3168e2019-01-23 17:54:08 +09005263 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005264 vpnNetworkAgent.setNetworkValid();
5265
Chalard Jean0b214af2018-01-12 17:22:49 +09005266 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005267 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005268 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005269
5270 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005271 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005272 wifiNetworkCallback.assertNoCallback();
5273 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005274 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5275 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005276
5277 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005278 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09005279 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005280 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5281 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005282
5283 ranges.clear();
5284 vpnNetworkAgent.setUids(ranges);
5285
5286 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005287 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005288 wifiNetworkCallback.assertNoCallback();
5289 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5290
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005291 // TODO : The default network callback should actually get a LOST call here (also see the
5292 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5293 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5294 // can't currently update their UIDs without disconnecting, so this does not matter too
5295 // much, but that is the reason the test here has to check for an update to the
5296 // capabilities instead of the expected LOST then AVAILABLE.
5297 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5298
Chalard Jean0b214af2018-01-12 17:22:49 +09005299 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005300 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005301 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005302
5303 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005304 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005305 wifiNetworkCallback.assertNoCallback();
5306 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005307 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5308 // happen outside of the test, ConnectivityService does not rematch callbacks.
5309 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005310
5311 mWiFiNetworkAgent.disconnect();
5312
5313 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005314 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005315 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5316 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005317 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005318
5319 vpnNetworkAgent.disconnect();
5320
5321 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005322 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005323 wifiNetworkCallback.assertNoCallback();
5324 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005325 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5326 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005327
5328 mCm.unregisterNetworkCallback(genericNetworkCallback);
5329 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5330 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005331 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005332 }
Chalard Jean26400492018-04-18 20:18:38 +09005333
5334 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005335 public void testVpnWithoutInternet() {
Chalard Jean26400492018-04-18 20:18:38 +09005336 final int uid = Process.myUid();
5337
5338 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5339 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005340
5341 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5342 mWiFiNetworkAgent.connect(true);
5343
5344 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5345 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5346
5347 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5348 final ArraySet<UidRange> ranges = new ArraySet<>();
5349 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005350 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5351 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005352 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005353 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005354
5355 defaultCallback.assertNoCallback();
5356 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5357
5358 vpnNetworkAgent.disconnect();
5359 defaultCallback.assertNoCallback();
5360
Varun Anand4fa80e82019-02-06 10:13:38 -08005361 mCm.unregisterNetworkCallback(defaultCallback);
5362 }
5363
5364 @Test
5365 public void testVpnWithInternet() {
5366 final int uid = Process.myUid();
5367
5368 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5369 mCm.registerDefaultNetworkCallback(defaultCallback);
5370
5371 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5372 mWiFiNetworkAgent.connect(true);
5373
5374 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5375 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5376
5377 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5378 final ArraySet<UidRange> ranges = new ArraySet<>();
5379 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005380 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5381 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005382 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005383 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005384
Chalard Jean26400492018-04-18 20:18:38 +09005385 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5386 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5387
5388 vpnNetworkAgent.disconnect();
5389 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5390 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5391
Chalard Jean26400492018-04-18 20:18:38 +09005392 mCm.unregisterNetworkCallback(defaultCallback);
5393 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005394
5395 @Test
5396 public void testVpnSetUnderlyingNetworks() {
5397 final int uid = Process.myUid();
5398
5399 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5400 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5401 .removeCapability(NET_CAPABILITY_NOT_VPN)
5402 .addTransportType(TRANSPORT_VPN)
5403 .build();
5404 NetworkCapabilities nc;
5405 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5406 vpnNetworkCallback.assertNoCallback();
5407
5408 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5409 final ArraySet<UidRange> ranges = new ArraySet<>();
5410 ranges.add(new UidRange(uid, uid));
5411 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5412 mMockVpn.connect();
5413 mMockVpn.setUids(ranges);
5414 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5415
5416 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5417 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5418 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5419 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5420 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5421 // For safety reasons a VPN without underlying networks is considered metered.
5422 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5423
5424 // Connect cell and use it as an underlying network.
5425 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5426 mCellNetworkAgent.connect(true);
5427
5428 mService.setUnderlyingNetworksForVpn(
5429 new Network[] { mCellNetworkAgent.getNetwork() });
5430
5431 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5432 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5433 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5434 vpnNetworkAgent);
5435
5436 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5437 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5438 mWiFiNetworkAgent.connect(true);
5439
5440 mService.setUnderlyingNetworksForVpn(
5441 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5442
5443 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5444 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5445 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5446 vpnNetworkAgent);
5447
5448 // Don't disconnect, but note the VPN is not using wifi any more.
5449 mService.setUnderlyingNetworksForVpn(
5450 new Network[] { mCellNetworkAgent.getNetwork() });
5451
5452 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5453 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5454 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5455 vpnNetworkAgent);
5456
5457 // Use Wifi but not cell. Note the VPN is now unmetered.
5458 mService.setUnderlyingNetworksForVpn(
5459 new Network[] { mWiFiNetworkAgent.getNetwork() });
5460
5461 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5462 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5463 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5464 vpnNetworkAgent);
5465
5466 // Use both again.
5467 mService.setUnderlyingNetworksForVpn(
5468 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5469
5470 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5471 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5472 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5473 vpnNetworkAgent);
5474
Chalard Jean6b65ec72018-05-18 22:02:56 +09005475 // Disconnect cell. Receive update without even removing the dead network from the
5476 // underlying networks – it's dead anyway. Not metered any more.
5477 mCellNetworkAgent.disconnect();
5478 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5479 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5480 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5481 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005482
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005483 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005484 mWiFiNetworkAgent.disconnect();
5485 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5486 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005487 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09005488 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005489
5490 mMockVpn.disconnect();
5491 }
junyulai4a192e22018-06-13 15:00:37 +08005492
Mike Yuf9729752018-08-17 15:22:05 +08005493 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005494 public void testNullUnderlyingNetworks() {
5495 final int uid = Process.myUid();
5496
5497 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5498 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5499 .removeCapability(NET_CAPABILITY_NOT_VPN)
5500 .addTransportType(TRANSPORT_VPN)
5501 .build();
5502 NetworkCapabilities nc;
5503 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5504 vpnNetworkCallback.assertNoCallback();
5505
5506 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5507 final ArraySet<UidRange> ranges = new ArraySet<>();
5508 ranges.add(new UidRange(uid, uid));
5509 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5510 mMockVpn.connect();
5511 mMockVpn.setUids(ranges);
5512 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5513
5514 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5515 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5516 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5517 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5518 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5519 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5520 // In case of no default network, VPN is considered metered.
5521 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5522
5523 // Connect to Cell; Cell is the default network.
5524 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5525 mCellNetworkAgent.connect(true);
5526
5527 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5528 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5529 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5530 vpnNetworkAgent);
5531
5532 // Connect to WiFi; WiFi is the new default.
5533 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5534 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5535 mWiFiNetworkAgent.connect(true);
5536
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);
5541
5542 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5543 // the capabilities.
5544 mCellNetworkAgent.disconnect();
5545
5546 // Disconnect wifi too. Now we have no default network.
5547 mWiFiNetworkAgent.disconnect();
5548
5549 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5550 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5551 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5552 vpnNetworkAgent);
5553
5554 mMockVpn.disconnect();
5555 }
5556
5557 @Test
Varun Anandc51b06d2019-02-25 17:22:02 -08005558 public void testIsActiveNetworkMeteredOverWifi() {
5559 // Returns true by default when no network is available.
5560 assertTrue(mCm.isActiveNetworkMetered());
5561 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5562 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5563 mWiFiNetworkAgent.connect(true);
5564 waitForIdle();
5565
5566 assertFalse(mCm.isActiveNetworkMetered());
5567 }
5568
5569 @Test
5570 public void testIsActiveNetworkMeteredOverCell() {
5571 // Returns true by default when no network is available.
5572 assertTrue(mCm.isActiveNetworkMetered());
5573 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5574 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5575 mCellNetworkAgent.connect(true);
5576 waitForIdle();
5577
5578 assertTrue(mCm.isActiveNetworkMetered());
5579 }
5580
5581 @Test
5582 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
5583 // Returns true by default when no network is available.
5584 assertTrue(mCm.isActiveNetworkMetered());
5585 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5586 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5587 mCellNetworkAgent.connect(true);
5588 waitForIdle();
5589 assertTrue(mCm.isActiveNetworkMetered());
5590
5591 // Connect VPN network. By default it is using current default network (Cell).
5592 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5593 final ArraySet<UidRange> ranges = new ArraySet<>();
5594 final int uid = Process.myUid();
5595 ranges.add(new UidRange(uid, uid));
5596 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5597 mMockVpn.setUids(ranges);
5598 vpnNetworkAgent.connect(true);
5599 mMockVpn.connect();
5600 waitForIdle();
5601 // Ensure VPN is now the active network.
5602 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5603
5604 // Expect VPN to be metered.
5605 assertTrue(mCm.isActiveNetworkMetered());
5606
5607 // Connect WiFi.
5608 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5609 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5610 mWiFiNetworkAgent.connect(true);
5611 waitForIdle();
5612 // VPN should still be the active network.
5613 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5614
5615 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5616 assertFalse(mCm.isActiveNetworkMetered());
5617
5618 // Disconnecting Cell should not affect VPN's meteredness.
5619 mCellNetworkAgent.disconnect();
5620 waitForIdle();
5621
5622 assertFalse(mCm.isActiveNetworkMetered());
5623
5624 // Disconnect WiFi; Now there is no platform default network.
5625 mWiFiNetworkAgent.disconnect();
5626 waitForIdle();
5627
5628 // VPN without any underlying networks is treated as metered.
5629 assertTrue(mCm.isActiveNetworkMetered());
5630
5631 vpnNetworkAgent.disconnect();
5632 mMockVpn.disconnect();
5633 }
5634
5635 @Test
5636 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
5637 // Returns true by default when no network is available.
5638 assertTrue(mCm.isActiveNetworkMetered());
5639 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5640 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5641 mCellNetworkAgent.connect(true);
5642 waitForIdle();
5643 assertTrue(mCm.isActiveNetworkMetered());
5644
5645 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5646 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5647 mWiFiNetworkAgent.connect(true);
5648 waitForIdle();
5649 assertFalse(mCm.isActiveNetworkMetered());
5650
5651 // Connect VPN network.
5652 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5653 final ArraySet<UidRange> ranges = new ArraySet<>();
5654 final int uid = Process.myUid();
5655 ranges.add(new UidRange(uid, uid));
5656 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5657 mMockVpn.setUids(ranges);
5658 vpnNetworkAgent.connect(true);
5659 mMockVpn.connect();
5660 waitForIdle();
5661 // Ensure VPN is now the active network.
5662 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5663 // VPN is using Cell
5664 mService.setUnderlyingNetworksForVpn(
5665 new Network[] { mCellNetworkAgent.getNetwork() });
5666 waitForIdle();
5667
5668 // Expect VPN to be metered.
5669 assertTrue(mCm.isActiveNetworkMetered());
5670
5671 // VPN is now using WiFi
5672 mService.setUnderlyingNetworksForVpn(
5673 new Network[] { mWiFiNetworkAgent.getNetwork() });
5674 waitForIdle();
5675
5676 // Expect VPN to be unmetered
5677 assertFalse(mCm.isActiveNetworkMetered());
5678
5679 // VPN is using Cell | WiFi.
5680 mService.setUnderlyingNetworksForVpn(
5681 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5682 waitForIdle();
5683
5684 // Expect VPN to be metered.
5685 assertTrue(mCm.isActiveNetworkMetered());
5686
5687 // VPN is using WiFi | Cell.
5688 mService.setUnderlyingNetworksForVpn(
5689 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5690 waitForIdle();
5691
5692 // Order should not matter and VPN should still be metered.
5693 assertTrue(mCm.isActiveNetworkMetered());
5694
5695 // VPN is not using any underlying networks.
5696 mService.setUnderlyingNetworksForVpn(new Network[0]);
5697 waitForIdle();
5698
5699 // VPN without underlying networks is treated as metered.
5700 assertTrue(mCm.isActiveNetworkMetered());
5701
5702 vpnNetworkAgent.disconnect();
5703 mMockVpn.disconnect();
5704 }
5705
5706 @Test
5707 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
5708 // Returns true by default when no network is available.
5709 assertTrue(mCm.isActiveNetworkMetered());
5710 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5711 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5712 mWiFiNetworkAgent.connect(true);
5713 waitForIdle();
5714 assertFalse(mCm.isActiveNetworkMetered());
5715
5716 // Connect VPN network.
5717 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5718 final ArraySet<UidRange> ranges = new ArraySet<>();
5719 final int uid = Process.myUid();
5720 ranges.add(new UidRange(uid, uid));
5721 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5722 mMockVpn.setUids(ranges);
5723 vpnNetworkAgent.connect(true);
5724 mMockVpn.connectAsAlwaysMetered();
5725 waitForIdle();
5726 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5727
5728 // VPN is tracking current platform default (WiFi).
5729 mService.setUnderlyingNetworksForVpn(null);
5730 waitForIdle();
5731
5732 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5733 assertTrue(mCm.isActiveNetworkMetered());
5734
5735 // VPN explicitly declares WiFi as its underlying network.
5736 mService.setUnderlyingNetworksForVpn(
5737 new Network[] { mWiFiNetworkAgent.getNetwork() });
5738 waitForIdle();
5739
5740 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5741 assertTrue(mCm.isActiveNetworkMetered());
5742
5743 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5744 // anyways suppose to be metered.
5745 mWiFiNetworkAgent.disconnect();
5746 waitForIdle();
5747
5748 assertTrue(mCm.isActiveNetworkMetered());
5749
5750 vpnNetworkAgent.disconnect();
5751 }
5752
5753 @Test
Mike Yuf9729752018-08-17 15:22:05 +08005754 public void testNetworkBlockedStatus() {
5755 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5756 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5757 .addTransportType(TRANSPORT_CELLULAR)
5758 .build();
5759 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5760
5761 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5762 mCellNetworkAgent.connect(true);
5763 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5764
5765 mService.setUidRulesChanged(RULE_REJECT_ALL);
5766 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5767
5768 // ConnectivityService should cache it not to invoke the callback again.
5769 mService.setUidRulesChanged(RULE_REJECT_METERED);
5770 cellNetworkCallback.assertNoCallback();
5771
5772 mService.setUidRulesChanged(RULE_NONE);
5773 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5774
5775 mService.setUidRulesChanged(RULE_REJECT_METERED);
5776 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5777
5778 // Restrict the network based on UID rule and NOT_METERED capability change.
5779 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5780 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5781 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5782 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5783 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5784 mCellNetworkAgent);
5785 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5786 mService.setUidRulesChanged(RULE_ALLOW_METERED);
5787 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5788
5789 mService.setUidRulesChanged(RULE_NONE);
5790 cellNetworkCallback.assertNoCallback();
5791
5792 // Restrict the network based on BackgroundRestricted.
5793 mService.setRestrictBackgroundChanged(true);
5794 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5795 mService.setRestrictBackgroundChanged(true);
5796 cellNetworkCallback.assertNoCallback();
5797 mService.setRestrictBackgroundChanged(false);
5798 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5799 cellNetworkCallback.assertNoCallback();
5800
5801 mCm.unregisterNetworkCallback(cellNetworkCallback);
5802 }
5803
5804 @Test
5805 public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5806 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5807 mCm.registerDefaultNetworkCallback(defaultCallback);
5808
5809 // No Networkcallbacks invoked before any network is active.
5810 mService.setUidRulesChanged(RULE_REJECT_ALL);
5811 mService.setUidRulesChanged(RULE_NONE);
5812 mService.setUidRulesChanged(RULE_REJECT_METERED);
5813 defaultCallback.assertNoCallback();
5814
5815 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5816 mCellNetworkAgent.connect(true);
5817 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5818 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5819
5820 // Allow to use the network after switching to NOT_METERED network.
5821 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5822 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5823 mWiFiNetworkAgent.connect(true);
5824 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5825
5826 // Switch to METERED network. Restrict the use of the network.
5827 mWiFiNetworkAgent.disconnect();
5828 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5829 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5830
5831 // Network becomes NOT_METERED.
5832 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5833 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5834 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5835
5836 // Verify there's no Networkcallbacks invoked after data saver on/off.
5837 mService.setRestrictBackgroundChanged(true);
5838 mService.setRestrictBackgroundChanged(false);
5839 defaultCallback.assertNoCallback();
5840
5841 mCellNetworkAgent.disconnect();
5842 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5843 defaultCallback.assertNoCallback();
5844
5845 mCm.unregisterNetworkCallback(defaultCallback);
5846 }
5847
junyulai4a192e22018-06-13 15:00:37 +08005848 /**
5849 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5850 */
5851 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5852 InterfaceConfiguration cfg = new InterfaceConfiguration();
5853 cfg.setHardwareAddress("11:22:33:44:55:66");
5854 cfg.setLinkAddress(la);
5855 return cfg;
5856 }
5857
5858 /**
5859 * Make expected stack link properties, copied from Nat464Xlat.
5860 */
5861 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5862 LinkAddress clatAddress = la;
5863 LinkProperties stacked = new LinkProperties();
5864 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5865 RouteInfo ipv4Default = new RouteInfo(
5866 new LinkAddress(Inet4Address.ANY, 0),
5867 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5868 stacked.addRoute(ipv4Default);
5869 stacked.addLinkAddress(clatAddress);
5870 return stacked;
5871 }
5872
5873 @Test
5874 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
5875 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5876 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005877 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5878 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5879
junyulai4a192e22018-06-13 15:00:37 +08005880 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5881 .addTransportType(TRANSPORT_CELLULAR)
5882 .addCapability(NET_CAPABILITY_INTERNET)
5883 .build();
5884 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5885 mCm.registerNetworkCallback(networkRequest, networkCallback);
5886
Lorenzo Colittid593e292019-02-19 13:21:56 +09005887 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005888 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005889 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005890 final LinkProperties cellLp = new LinkProperties();
5891 cellLp.setInterfaceName(MOBILE_IFNAME);
5892 cellLp.addLinkAddress(myIpv6);
5893 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5894 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5895 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005896 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005897 reset(mMockNetd);
junyulai4a192e22018-06-13 15:00:37 +08005898 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5899 .thenReturn(getClatInterfaceConfig(myIpv4));
5900
Lorenzo Colittid593e292019-02-19 13:21:56 +09005901 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005902 mCellNetworkAgent.sendLinkProperties(cellLp);
5903 mCellNetworkAgent.connect(true);
Luke Huanga24d5d82019-04-09 18:41:49 +08005904
5905 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
5906 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
5907
junyulai4a192e22018-06-13 15:00:37 +08005908 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005909 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005910
Lorenzo Colittid593e292019-02-19 13:21:56 +09005911 // Switching default network updates TCP buffer sizes.
5912 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5913
5914 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5915 // the NAT64 prefix was removed because one was never discovered.
5916 cellLp.addLinkAddress(myIpv4);
5917 mCellNetworkAgent.sendLinkProperties(cellLp);
5918 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005919 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005920 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005921
5922 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005923 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005924 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005925 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005926
5927 // Remove IPv4 address. Expect prefix discovery to be started again.
5928 cellLp.removeLinkAddress(myIpv4);
5929 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5930 mCellNetworkAgent.sendLinkProperties(cellLp);
5931 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005932 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005933
5934 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005935 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
5936 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005937 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5938 kNat64PrefixString, 96);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005939 LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
5940 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
5941 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5942 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5943 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5944
5945 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005946 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005947 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005948 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5949 .getStackedLinks();
5950 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5951
5952 // Change trivial linkproperties and see if stacked link is preserved.
5953 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5954 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005955 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5956
5957 List<LinkProperties> stackedLpsAfterChange =
5958 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5959 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5960 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5961
Luke Huang65914772019-03-16 00:31:46 +08005962 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005963 mResolverParamsParcelCaptor.capture());
5964 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5965 assertEquals(1, resolvrParams.servers.length);
5966 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08005967
Lorenzo Colittid593e292019-02-19 13:21:56 +09005968 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5969 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005970 cellLp.addLinkAddress(myIpv4);
5971 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5972 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005973 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005974 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08005975 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005976
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005977 // As soon as stop is called, the linkproperties lose the stacked interface.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005978 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005979 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
5980 LinkProperties expected = new LinkProperties(cellLp);
5981 expected.setNat64Prefix(kNat64Prefix);
5982 assertEquals(expected, actualLpAfterIpv4);
5983 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
5984
5985 // The interface removed callback happens but has no effect after stop is called.
5986 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5987 networkCallback.assertNoCallback();
5988
Lorenzo Colittid593e292019-02-19 13:21:56 +09005989 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005990 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005991 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005992 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005993
Lorenzo Colittid593e292019-02-19 13:21:56 +09005994 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5995 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5996 kNat64PrefixString, 96);
5997 networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
5998 mCellNetworkAgent);
5999
6000 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006001 cellLp.removeLinkAddress(myIpv4);
6002 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6003 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6004 mCellNetworkAgent.sendLinkProperties(cellLp);
6005 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006006 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006007 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6008 kNat64PrefixString, 96);
6009 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006010 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6011
Lorenzo Colittid593e292019-02-19 13:21:56 +09006012
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006013 // Clat iface comes up. Expect stacked link to be added.
6014 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006015 networkCallback.expectLinkPropertiesLike(
6016 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006017 mCellNetworkAgent);
6018
6019 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006020 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6021 kNat64PrefixString, 96);
6022 networkCallback.expectLinkPropertiesLike(
6023 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006024 mCellNetworkAgent);
6025 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6026 networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
6027 mCellNetworkAgent);
6028
6029 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08006030 mCellNetworkAgent.disconnect();
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006031 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6032 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08006033 mCm.unregisterNetworkCallback(networkCallback);
6034 }
Chiachang Wanga6093042018-09-28 22:42:48 +08006035
6036 @Test
6037 public void testDataActivityTracking() throws RemoteException {
6038 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6039 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6040 .addCapability(NET_CAPABILITY_INTERNET)
6041 .build();
6042 mCm.registerNetworkCallback(networkRequest, networkCallback);
6043
6044 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6045 final LinkProperties cellLp = new LinkProperties();
6046 cellLp.setInterfaceName(MOBILE_IFNAME);
6047 mCellNetworkAgent.sendLinkProperties(cellLp);
6048 reset(mNetworkManagementService);
6049 mCellNetworkAgent.connect(true);
6050 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6051 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6052 eq(ConnectivityManager.TYPE_MOBILE));
6053
6054 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6055 final LinkProperties wifiLp = new LinkProperties();
6056 wifiLp.setInterfaceName(WIFI_IFNAME);
6057 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6058
6059 // Network switch
6060 reset(mNetworkManagementService);
6061 mWiFiNetworkAgent.connect(true);
6062 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6063 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6064 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6065 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6066 eq(ConnectivityManager.TYPE_WIFI));
6067 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6068
6069 // Disconnect wifi and switch back to cell
6070 reset(mNetworkManagementService);
6071 mWiFiNetworkAgent.disconnect();
6072 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
6073 assertNoCallbacks(networkCallback);
6074 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6075 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6076 eq(ConnectivityManager.TYPE_MOBILE));
6077
6078 // reconnect wifi
6079 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6080 wifiLp.setInterfaceName(WIFI_IFNAME);
6081 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6082 mWiFiNetworkAgent.connect(true);
6083 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6084 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6085 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6086
6087 // Disconnect cell
6088 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006089 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006090 mCellNetworkAgent.disconnect();
6091 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6092 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6093 // sent as network being switched. Ensure rule removal for cell will not be triggered
6094 // unexpectedly before network being removed.
6095 waitForIdle();
6096 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006097 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6098 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08006099 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006100
6101 // Disconnect wifi
6102 ConditionVariable cv = waitForConnectivityBroadcasts(1);
6103 reset(mNetworkManagementService);
6104 mWiFiNetworkAgent.disconnect();
6105 waitFor(cv);
6106 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6107
6108 // Clean up
6109 mCm.unregisterNetworkCallback(networkCallback);
6110 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006111
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006112 private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006113 String[] values = tcpBufferSizes.split(",");
6114 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6115 String wmemValues = String.join(" ", values[3], values[4], values[5]);
6116 waitForIdle();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006117 try {
6118 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
6119 } catch (RemoteException e) {
6120 fail("mMockNetd should never throw RemoteException");
6121 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006122 reset(mMockNetd);
6123 }
6124
6125 @Test
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006126 public void testTcpBufferReset() {
6127 final String testTcpBufferSizes = "1,2,3,4,5,6";
6128
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006129 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6130 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006131 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006132 mCellNetworkAgent.connect(false);
6133 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6134
6135 // Change link Properties should have updated tcp buffer size.
6136 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006137 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006138 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006139 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006140 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006141
6142 @Test
6143 public void testGetGlobalProxyForNetwork() {
6144 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6145 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6146 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6147 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6148 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6149 }
6150
6151 @Test
6152 public void testGetProxyForActiveNetwork() {
6153 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6154 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6155 mWiFiNetworkAgent.connect(true);
6156 waitForIdle();
6157 assertNull(mService.getProxyForNetwork(null));
6158
6159 final LinkProperties testLinkProperties = new LinkProperties();
6160 testLinkProperties.setHttpProxy(testProxyInfo);
6161
6162 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6163 waitForIdle();
6164
6165 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6166 }
6167
6168 @Test
6169 public void testGetProxyForVPN() {
6170 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6171
6172 // Set up a WiFi network with no proxy
6173 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6174 mWiFiNetworkAgent.connect(true);
6175 waitForIdle();
6176 assertNull(mService.getProxyForNetwork(null));
6177
6178 // Set up a VPN network with a proxy
6179 final int uid = Process.myUid();
6180 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
6181 final ArraySet<UidRange> ranges = new ArraySet<>();
6182 ranges.add(new UidRange(uid, uid));
6183 mMockVpn.setUids(ranges);
6184 LinkProperties testLinkProperties = new LinkProperties();
6185 testLinkProperties.setHttpProxy(testProxyInfo);
6186 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6187 waitForIdle();
6188
6189 // Connect to VPN with proxy
6190 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6191 vpnNetworkAgent.connect(true);
6192 mMockVpn.connect();
6193 waitForIdle();
6194
6195 // Test that the VPN network returns a proxy, and the WiFi does not.
6196 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6197 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6198 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6199
6200 // Test that the VPN network returns no proxy when it is set to null.
6201 testLinkProperties.setHttpProxy(null);
6202 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6203 waitForIdle();
6204 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6205 assertNull(mService.getProxyForNetwork(null));
6206
6207 // Set WiFi proxy and check that the vpn proxy is still null.
6208 testLinkProperties.setHttpProxy(testProxyInfo);
6209 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6210 waitForIdle();
6211 assertNull(mService.getProxyForNetwork(null));
6212
6213 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6214 // correct proxy setting.
6215 vpnNetworkAgent.disconnect();
6216 waitForIdle();
6217 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6218 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6219 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6220 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006221
6222 @Test
6223 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6224 LinkProperties lp = new LinkProperties();
6225 lp.setInterfaceName("tun0");
6226 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6227 // The uid range needs to cover the test app so the network is visible to it.
6228 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6229 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6230
6231 // Connected VPN should have interface rules set up. There are two expected invocations,
6232 // one during VPN uid update, one during VPN LinkProperties update
6233 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6234 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6235 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6236 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6237 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6238
6239 vpnNetworkAgent.disconnect();
6240 waitForIdle();
6241
6242 // Disconnected VPN should have interface rules removed
6243 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6244 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6245 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6246 }
6247
6248 @Test
6249 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6250 LinkProperties lp = new LinkProperties();
6251 lp.setInterfaceName("tun0");
6252 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6253 // The uid range needs to cover the test app so the network is visible to it.
6254 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6255 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6256
6257 // Legacy VPN should not have interface rules set up
6258 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6259 }
6260
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09006261 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006262 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6263 throws Exception {
6264 LinkProperties lp = new LinkProperties();
6265 lp.setInterfaceName("tun0");
6266 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6267 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6268 // The uid range needs to cover the test app so the network is visible to it.
6269 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6270 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6271
6272 // IPv6 unreachable route should not be misinterpreted as a default route
6273 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6274 }
6275
6276 @Test
6277 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6278 LinkProperties lp = new LinkProperties();
6279 lp.setInterfaceName("tun0");
6280 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6281 // The uid range needs to cover the test app so the network is visible to it.
6282 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6283 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6284
6285 // Connected VPN should have interface rules set up. There are two expected invocations,
6286 // one during VPN uid update, one during VPN LinkProperties update
6287 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6288 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6289 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6290 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6291
6292 reset(mMockNetd);
6293 InOrder inOrder = inOrder(mMockNetd);
6294 lp.setInterfaceName("tun1");
6295 vpnNetworkAgent.sendLinkProperties(lp);
6296 waitForIdle();
6297 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6298 // removed first, then new rules added)
6299 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6300 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6301 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6302 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6303
6304 reset(mMockNetd);
6305 lp = new LinkProperties();
6306 lp.setInterfaceName("tun1");
6307 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6308 vpnNetworkAgent.sendLinkProperties(lp);
6309 waitForIdle();
6310 // VPN not routing everything should no longer have interface filtering rules
6311 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6312 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6313
6314 reset(mMockNetd);
6315 lp = new LinkProperties();
6316 lp.setInterfaceName("tun1");
6317 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6318 vpnNetworkAgent.sendLinkProperties(lp);
6319 waitForIdle();
6320 // Back to routing all IPv6 traffic should have filtering rules
6321 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6322 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6323 }
6324
6325 @Test
6326 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6327 LinkProperties lp = new LinkProperties();
6328 lp.setInterfaceName("tun0");
6329 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6330 // The uid range needs to cover the test app so the network is visible to it.
6331 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
6332 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID,
6333 Collections.singleton(vpnRange));
6334
6335 reset(mMockNetd);
6336 InOrder inOrder = inOrder(mMockNetd);
6337
6338 // Update to new range which is old range minus APP1, i.e. only APP2
6339 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6340 new UidRange(vpnRange.start, APP1_UID - 1),
6341 new UidRange(APP1_UID + 1, vpnRange.stop)));
6342 vpnNetworkAgent.setUids(newRanges);
6343 waitForIdle();
6344
6345 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6346 // Verify old rules are removed before new rules are added
6347 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6348 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6349 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6350 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6351 }
6352
6353
6354 private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
6355 Set<UidRange> vpnRange) {
6356 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
6357 vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
6358 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6359 mMockVpn.connect();
6360 mMockVpn.setUids(vpnRange);
6361 vpnNetworkAgent.connect(true);
6362 waitForIdle();
6363 return vpnNetworkAgent;
6364 }
6365
6366 private void assertContainsExactly(int[] actual, int... expected) {
6367 int[] sortedActual = Arrays.copyOf(actual, actual.length);
6368 int[] sortedExpected = Arrays.copyOf(expected, expected.length);
6369 Arrays.sort(sortedActual);
6370 Arrays.sort(sortedExpected);
6371 assertArrayEquals(sortedExpected, sortedActual);
6372 }
6373
6374 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6375 final PackageInfo packageInfo = new PackageInfo();
6376 packageInfo.requestedPermissions = new String[0];
6377 packageInfo.applicationInfo = new ApplicationInfo();
6378 packageInfo.applicationInfo.privateFlags = 0;
6379 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6380 UserHandle.getAppId(uid));
6381 return packageInfo;
6382 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006383}