blob: d29234fbf1717281dfa0f3c70193a4f5bc6574cc [file] [log] [blame]
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Erik Klinef851d6d2015-04-20 16:03:48 +090019import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090020import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070021import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
22import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
23import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090024import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070025import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090026import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
27import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Hugo Benichi16f0a942017-06-20 14:07:59 +090028import static android.net.ConnectivityManager.TYPE_NONE;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070029import static android.net.ConnectivityManager.TYPE_WIFI;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090030import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
31import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060032import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
33import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
34import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
35import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
36import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
38import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
39import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
40import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090044import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060045import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
46import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
47import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
48import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
52import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
53import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090054import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060055import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
56import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080057import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
58import static android.net.NetworkPolicyManager.RULE_NONE;
59import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
60import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090061import static android.net.shared.NetworkParcelableUtil.fromStableParcelable;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060062
63import static com.android.internal.util.TestUtils.waitForIdleHandler;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090064import static com.android.internal.util.TestUtils.waitForIdleLooper;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090065
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090066import static org.junit.Assert.assertEquals;
67import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080068import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090069import static org.junit.Assert.assertNotNull;
70import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060071import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090072import static org.junit.Assert.fail;
Erik Klinee89953b2018-01-11 16:11:10 +090073import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +090074import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060075import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090076import static org.mockito.Mockito.doAnswer;
77import static org.mockito.Mockito.doNothing;
Erik Kline117e7f32018-03-04 21:01:01 +090078import static org.mockito.Mockito.eq;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080079import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060080import static org.mockito.Mockito.never;
81import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090082import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090083import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +090084import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060085import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -070086import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090087import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070088
Lorenzo Colitti73b209382016-09-15 22:18:09 +090089import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -040090import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -040091import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +090092import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +090093import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070094import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -040095import android.content.Intent;
96import android.content.IntentFilter;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090097import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -040098import android.net.ConnectivityManager;
99import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900100import android.net.ConnectivityManager.PacketKeepalive;
101import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900102import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900103import android.net.ConnectivityThread;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800104import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900105import android.net.INetworkMonitor;
106import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800107import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700108import android.net.INetworkPolicyManager;
109import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800110import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900111import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800112import android.net.IpSecManager;
113import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900114import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700115import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700116import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400117import android.net.Network;
118import android.net.NetworkAgent;
119import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700120import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700121import android.net.NetworkInfo;
122import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400123import android.net.NetworkMisc;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900124import android.net.NetworkParcelable;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400125import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700126import android.net.NetworkSpecifier;
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900127import android.net.NetworkStackClient;
Varun Anand02c50ef2019-02-07 14:13:13 -0800128import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100129import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000130import android.net.ProxyInfo;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700131import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800132import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900133import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900134import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900135import android.net.shared.NetworkMonitorUtils;
136import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900137import android.net.util.MultinetworkPolicyTracker;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400138import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700139import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700140import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700141import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900142import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900143import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700144import android.os.Parcel;
145import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000146import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800147import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900148import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900149import android.os.UserHandle;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900150import android.provider.Settings;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900151import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800152import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100153import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700154import android.util.Log;
Etan Cohenae574a82019-01-08 12:09:18 -0800155import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700156
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800157import androidx.test.InstrumentationRegistry;
158import androidx.test.filters.SmallTest;
159import androidx.test.runner.AndroidJUnit4;
160
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900161import com.android.internal.net.VpnConfig;
Varun Anand02c50ef2019-02-07 14:13:13 -0800162import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900163import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900164import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900165import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900166import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900167import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900168import com.android.server.connectivity.DefaultNetworkMetrics;
169import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900170import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800171import com.android.server.connectivity.Nat464Xlat;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000172import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800173import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900174import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900175import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900176import com.android.server.net.NetworkPolicyManagerInternal;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400177
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900178import org.junit.After;
179import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900180import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900181import org.junit.Test;
182import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900183import org.mockito.ArgumentCaptor;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900184import org.mockito.Mock;
185import org.mockito.MockitoAnnotations;
186import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900187import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900188
junyulai4a192e22018-06-13 15:00:37 +0800189import java.net.Inet4Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700190import java.net.InetAddress;
junyulai4a192e22018-06-13 15:00:37 +0800191import java.net.UnknownHostException;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400192import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900193import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100194import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800195import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500196import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100197import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900198import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100199import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900200import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800201import java.util.concurrent.Executor;
junyulaie4135282019-01-03 18:50:15 +0800202import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800203import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900204import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900205import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700206import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900207import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700208
209/**
210 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400211 *
212 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900213 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700214 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900215@RunWith(AndroidJUnit4.class)
216@SmallTest
217public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700218 private static final String TAG = "ConnectivityServiceTest";
219
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900220 private static final int TIMEOUT_MS = 500;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900221 private static final int TEST_LINGER_DELAY_MS = 250;
222 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
223 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
224 // timeout. For this, our assertions should run fast enough to leave less than
225 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
226 // supposedly fired, and the time we call expectCallback.
227 private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900228 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
229 // complete before callbacks are verified.
230 private final static int TEST_REQUEST_TIMEOUT_MS = 150;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900231
junyulai4a192e22018-06-13 15:00:37 +0800232 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700233 private static final String MOBILE_IFNAME = "test_rmnet_data0";
234 private static final String WIFI_IFNAME = "test_wlan0";
235
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900236 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400237 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900238 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400239 private MockNetworkAgent mWiFiNetworkAgent;
240 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900241 private MockNetworkAgent mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900242 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900243 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800244 private INetworkPolicyListener mPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700245
Hugo Benichi64901e52017-10-19 14:42:40 +0900246 @Mock IpConnectivityMetrics.Logger mMetricsService;
247 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900248 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600249 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800250 @Mock INetworkPolicyManager mNpm;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800251 @Mock INetd mMockNetd;
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900252 @Mock NetworkStackClient mNetworkStack;
Hugo Benichi64901e52017-10-19 14:42:40 +0900253
Erik Klinee89953b2018-01-11 16:11:10 +0900254 private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
255
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900256 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
257 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
258 // reflect the state of our test ConnectivityService.
259 private class WrappedConnectivityManager extends ConnectivityManager {
260 private Network mFakeBoundNetwork;
261
262 public synchronized boolean bindProcessToNetwork(Network network) {
263 mFakeBoundNetwork = network;
264 return true;
265 }
266
267 public synchronized Network getBoundNetworkForProcess() {
268 return mFakeBoundNetwork;
269 }
270
271 public WrappedConnectivityManager(Context context, ConnectivityService service) {
272 super(context, service);
273 }
274 }
275
Paul Jensend7b6ca92015-05-13 14:05:12 -0400276 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900277 private final MockContentResolver mContentResolver;
278
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900279 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900280 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900281
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900282 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400283 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900284
285 mResources = spy(base.getResources());
286 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
287 thenReturn(new String[] {
288 "wifi,1,1,1,-1,true",
289 "mobile,0,0,0,-1,true",
290 "mobile_mms,2,0,2,60000,true",
291 });
292
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900293 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900294 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400295 }
296
297 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900298 public void startActivityAsUser(Intent intent, UserHandle handle) {
299 mStartedActivities.offer(intent);
300 }
301
302 public Intent expectStartActivityIntent(int timeoutMs) {
303 Intent intent = null;
304 try {
305 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
306 } catch (InterruptedException e) {}
307 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
308 return intent;
309 }
310
311 public void expectNoStartActivityIntent(int timeoutMs) {
312 try {
313 assertNull("Received unexpected Intent to start activity",
314 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
315 } catch (InterruptedException e) {}
316 }
317
318 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900319 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900320 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
321 if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900322 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400323 return super.getSystemService(name);
324 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900325
326 @Override
327 public ContentResolver getContentResolver() {
328 return mContentResolver;
329 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900330
331 @Override
332 public Resources getResources() {
333 return mResources;
334 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400335 }
336
Hugo Benichi669f0232017-06-29 22:58:39 +0900337 public void waitForIdle(int timeoutMsAsInt) {
338 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900339 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
340 waitForIdle(mCellNetworkAgent, timeoutMs);
341 waitForIdle(mWiFiNetworkAgent, timeoutMs);
342 waitForIdle(mEthernetNetworkAgent, timeoutMs);
343 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900344 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900345 }
346
Hugo Benichi669f0232017-06-29 22:58:39 +0900347 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900348 if (agent == null) {
349 return;
350 }
351 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
352 }
353
354 private void waitForIdle() {
355 waitForIdle(TIMEOUT_MS);
356 }
357
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900358 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900359 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900360 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
361
362 // Tests that waitForIdle returns immediately if the service is already idle.
363 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900364 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900365 }
366
367 // Bring up a network that we can use to send messages to ConnectivityService.
368 ConditionVariable cv = waitForConnectivityBroadcasts(1);
369 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
370 mWiFiNetworkAgent.connect(false);
371 waitFor(cv);
372 Network n = mWiFiNetworkAgent.getNetwork();
373 assertNotNull(n);
374
375 // Tests that calling waitForIdle waits for messages to be processed.
376 for (int i = 0; i < attempts; i++) {
377 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900378 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900379 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
380 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900381 }
382
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900383 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
384 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800385 @Ignore
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900386 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900387 // Bring up a network that we can use to send messages to ConnectivityService.
388 ConditionVariable cv = waitForConnectivityBroadcasts(1);
389 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
390 mWiFiNetworkAgent.connect(false);
391 waitFor(cv);
392 Network n = mWiFiNetworkAgent.getNetwork();
393 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900394
395 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900396 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900397 for (int i = 0; i < attempts; i++) {
398 mWiFiNetworkAgent.setSignalStrength(i);
399 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
400 // We hit a race condition, as expected. Pass the test.
401 return;
402 }
403 }
404
405 // No race? There is a bug in this test.
406 fail("expected race condition at least once in " + attempts + " attempts");
407 }
408
Paul Jensend7b6ca92015-05-13 14:05:12 -0400409 private class MockNetworkAgent {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900410 private final INetworkMonitor mNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400411 private final NetworkInfo mNetworkInfo;
412 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900413 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400414 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400415 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700416 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400417 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400418 private NetworkAgent mNetworkAgent;
junyulai48eac1d42018-12-27 17:25:29 +0800419 private int mStartKeepaliveError = SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
420 private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900421 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400422 // Contains the redirectUrl from networkStatus(). Before reading, wait for
423 // mNetworkStatusReceived.
424 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400425
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900426 private INetworkMonitorCallbacks mNmCallbacks;
427 private int mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
428 private String mNmValidationRedirectUrl = null;
429 private boolean mNmProvNotificationRequested = false;
430
431 void setNetworkValid() {
432 mNmValidationResult = NETWORK_TEST_RESULT_VALID;
433 mNmValidationRedirectUrl = null;
434 }
435
436 void setNetworkInvalid() {
437 mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
438 mNmValidationRedirectUrl = null;
439 }
440
441 void setNetworkPortal(String redirectUrl) {
442 setNetworkInvalid();
443 mNmValidationRedirectUrl = redirectUrl;
444 }
445
Paul Jensend7b6ca92015-05-13 14:05:12 -0400446 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100447 this(transport, new LinkProperties());
448 }
449
450 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400451 final int type = transportToLegacyType(transport);
Chalard Jean0b214af2018-01-12 17:22:49 +0900452 final String typeName = ConnectivityManager.getNetworkTypeName(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400453 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
454 mNetworkCapabilities = new NetworkCapabilities();
455 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400456 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900457 case TRANSPORT_ETHERNET:
458 mScore = 70;
459 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400460 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400461 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400462 break;
463 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400464 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400465 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900466 case TRANSPORT_WIFI_AWARE:
467 mScore = 20;
468 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900469 case TRANSPORT_VPN:
Chalard Jeanb552c462018-02-21 18:43:54 +0900470 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
Chalard Jeandda156a2018-01-10 21:19:32 +0900471 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
Chalard Jean0b214af2018-01-12 17:22:49 +0900472 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400473 default:
474 throw new UnsupportedOperationException("unimplemented network type");
475 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900476 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900477 mHandlerThread.start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900478
479 mNetworkMonitor = mock(INetworkMonitor.class);
480 final Answer validateAnswer = inv -> {
481 new Thread(this::onValidationRequested).start();
482 return null;
483 };
484
485 try {
486 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected();
487 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
488 } catch (RemoteException e) {
489 fail(e.getMessage());
490 }
491
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900492 final ArgumentCaptor<NetworkParcelable> nmNetworkCaptor =
493 ArgumentCaptor.forClass(NetworkParcelable.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900494 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
495 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
496 doNothing().when(mNetworkStack).makeNetworkMonitor(
497 nmNetworkCaptor.capture(),
498 any() /* name */,
499 nmCbCaptor.capture());
500
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900501 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
502 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Chalard Jean08577fc2018-05-02 21:14:54 +0900503 linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900504 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900505 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900506
507 @Override
junyulaie4135282019-01-03 18:50:15 +0800508 public void startSocketKeepalive(Message msg) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900509 int slot = msg.arg1;
510 if (mExpectedKeepaliveSlot != null) {
511 assertEquals((int) mExpectedKeepaliveSlot, slot);
512 }
junyulaie4135282019-01-03 18:50:15 +0800513 onSocketKeepaliveEvent(slot, mStartKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900514 }
515
516 @Override
junyulaie4135282019-01-03 18:50:15 +0800517 public void stopSocketKeepalive(Message msg) {
518 onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900519 }
Paul Jensen232437312016-04-06 09:51:26 -0400520
521 @Override
522 public void networkStatus(int status, String redirectUrl) {
523 mRedirectUrl = redirectUrl;
524 mNetworkStatusReceived.open();
525 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700526
527 @Override
528 protected void preventAutomaticReconnect() {
529 mPreventReconnectReceived.open();
530 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400531 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900532
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900533 assertEquals(
534 mNetworkAgent.netId, fromStableParcelable(nmNetworkCaptor.getValue()).netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900535 mNmCallbacks = nmCbCaptor.getValue();
536
537 try {
538 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
539 } catch (RemoteException e) {
540 fail(e.getMessage());
541 }
542
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900543 // Waits for the NetworkAgent to be registered, which includes the creation of the
544 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900545 waitForIdle();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900546 }
547
548 private void onValidationRequested() {
549 try {
550 if (mNmProvNotificationRequested
551 && mNmValidationResult == NETWORK_TEST_RESULT_VALID) {
552 mNmCallbacks.hideProvisioningNotification();
553 mNmProvNotificationRequested = false;
554 }
555
556 mNmCallbacks.notifyNetworkTested(
557 mNmValidationResult, mNmValidationRedirectUrl);
558
559 if (mNmValidationRedirectUrl != null) {
560 mNmCallbacks.showProvisioningNotification(
Remi NGUYEN VAN9c5d9642019-02-07 21:29:57 +0900561 "test_provisioning_notif_action", "com.android.test.package");
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900562 mNmProvNotificationRequested = true;
563 }
564 } catch (RemoteException e) {
565 fail(e.getMessage());
566 }
Paul Jensen3d911462015-06-12 06:40:24 -0400567 }
568
569 public void adjustScore(int change) {
570 mScore += change;
571 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400572 }
573
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900574 public void explicitlySelected(boolean acceptUnvalidated) {
575 mNetworkAgent.explicitlySelected(acceptUnvalidated);
576 }
577
Paul Jensen85cf78e2015-06-25 13:25:07 -0400578 public void addCapability(int capability) {
579 mNetworkCapabilities.addCapability(capability);
580 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
581 }
582
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900583 public void removeCapability(int capability) {
584 mNetworkCapabilities.removeCapability(capability);
585 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
586 }
587
Chalard Jean0b214af2018-01-12 17:22:49 +0900588 public void setUids(Set<UidRange> uids) {
589 mNetworkCapabilities.setUids(uids);
590 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
591 }
592
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900593 public void setSignalStrength(int signalStrength) {
594 mNetworkCapabilities.setSignalStrength(signalStrength);
595 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
596 }
597
Etan Cohena7434272017-04-03 12:17:51 -0700598 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
599 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900600 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
601 }
602
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900603 public void setNetworkCapabilities(NetworkCapabilities nc,
604 boolean sendToConnectivityService) {
605 mNetworkCapabilities.set(nc);
606 if (sendToConnectivityService) {
607 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
608 }
609 }
610
Paul Jensene0988542015-06-25 15:30:08 -0400611 public void connectWithoutInternet() {
612 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
613 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
614 }
615
Paul Jensend7b6ca92015-05-13 14:05:12 -0400616 /**
Paul Jensene0988542015-06-25 15:30:08 -0400617 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400618 * @param validated Indicate if network should pretend to be validated.
619 */
620 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900621 connect(validated, true);
622 }
623
624 /**
625 * Transition this NetworkAgent to CONNECTED state.
626 * @param validated Indicate if network should pretend to be validated.
627 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
628 */
629 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900630 assertEquals("MockNetworkAgents can only be connected once",
631 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400632 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
633
Paul Jensend7b6ca92015-05-13 14:05:12 -0400634 NetworkCallback callback = null;
635 final ConditionVariable validatedCv = new ConditionVariable();
636 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900637 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400638 NetworkRequest request = new NetworkRequest.Builder()
639 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900640 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400641 .build();
642 callback = new NetworkCallback() {
643 public void onCapabilitiesChanged(Network network,
644 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400645 if (network.equals(getNetwork()) &&
646 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400647 validatedCv.open();
648 }
649 }
650 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400651 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400652 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900653 if (hasInternet) {
654 addCapability(NET_CAPABILITY_INTERNET);
655 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400656
Paul Jensene0988542015-06-25 15:30:08 -0400657 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400658
659 if (validated) {
660 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400661 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900662 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400663 }
664
665 if (callback != null) mCm.unregisterNetworkCallback(callback);
666 }
667
Paul Jensen232437312016-04-06 09:51:26 -0400668 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900669 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400670 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400671 }
672
Erik Kline1d3db322017-02-28 16:20:20 +0900673 public void suspend() {
674 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
675 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
676 }
677
Chalard Jean804b8fb2018-01-30 22:41:41 +0900678 public void resume() {
679 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
680 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
681 }
682
Paul Jensend7b6ca92015-05-13 14:05:12 -0400683 public void disconnect() {
684 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
685 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
686 }
687
688 public Network getNetwork() {
689 return new Network(mNetworkAgent.netId);
690 }
Paul Jensene0988542015-06-25 15:30:08 -0400691
Calvin On1f64f3f2016-10-11 15:10:46 -0700692 public ConditionVariable getPreventReconnectReceived() {
693 return mPreventReconnectReceived;
694 }
695
Paul Jensene0988542015-06-25 15:30:08 -0400696 public ConditionVariable getDisconnectedCV() {
697 return mDisconnected;
698 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400699
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900700 public void sendLinkProperties(LinkProperties lp) {
701 mNetworkAgent.sendLinkProperties(lp);
702 }
703
704 public void setStartKeepaliveError(int error) {
705 mStartKeepaliveError = error;
706 }
707
708 public void setStopKeepaliveError(int error) {
709 mStopKeepaliveError = error;
710 }
711
712 public void setExpectedKeepaliveSlot(Integer slot) {
713 mExpectedKeepaliveSlot = slot;
714 }
Paul Jensen232437312016-04-06 09:51:26 -0400715
716 public String waitForRedirectUrl() {
717 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
718 return mRedirectUrl;
719 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900720
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900721 public NetworkAgent getNetworkAgent() {
722 return mNetworkAgent;
723 }
724
Chalard Jean804b8fb2018-01-30 22:41:41 +0900725 public NetworkCapabilities getNetworkCapabilities() {
726 return mNetworkCapabilities;
727 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400728 }
729
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900730 /**
731 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
732 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean08577fc2018-05-02 21:14:54 +0900733 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900734 * expectRemoveRequests.
735 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700736 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400737 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
738 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400739 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700740
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900741 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean08577fc2018-05-02 21:14:54 +0900742 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
743 // once, then cause some other thread to add or remove requests, then call
744 // waitForRequests().
745 // It is not possible to wait for both add and remove requests. When adding, the queue
746 // contains the expected score. When removing, the value is unused, all matters is the
747 // number of objects in the queue.
748 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900749
750 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean08577fc2018-05-02 21:14:54 +0900751 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900752 private boolean mExpectingAdditions;
753
Etan Cohenae574a82019-01-08 12:09:18 -0800754 // Used to collect the networks requests managed by this factory. This is a duplicate of
755 // the internal information stored in the NetworkFactory (which is private).
756 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
757
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700758 public MockNetworkFactory(Looper looper, Context context, String logTag,
759 NetworkCapabilities filter) {
760 super(looper, context, logTag, filter);
Chalard Jean08577fc2018-05-02 21:14:54 +0900761 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700762 }
763
764 public int getMyRequestCount() {
765 return getRequestCount();
766 }
767
768 protected void startNetwork() {
769 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400770 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700771 }
772
773 protected void stopNetwork() {
774 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400775 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700776 }
777
778 public boolean getMyStartRequested() {
779 return mNetworkStarted.get();
780 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400781
782 public ConditionVariable getNetworkStartedCV() {
783 mNetworkStartedCV.close();
784 return mNetworkStartedCV;
785 }
786
787 public ConditionVariable getNetworkStoppedCV() {
788 mNetworkStoppedCV.close();
789 return mNetworkStoppedCV;
790 }
791
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900792 @Override
Chalard Jean08577fc2018-05-02 21:14:54 +0900793 protected void handleAddRequest(NetworkRequest request, int score,
794 int factorySerialNumber) {
795 synchronized (mExpectations) {
796 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900797
Chalard Jean08577fc2018-05-02 21:14:54 +0900798 assertNotNull("Added more requests than expected (" + request + " score : "
799 + score + ")", expectedScore);
800 // If we're expecting anything, we must be expecting additions.
801 if (!mExpectingAdditions) {
802 fail("Can't add requests while expecting requests to be removed");
803 }
804 if (expectedScore != score) {
805 fail("Expected score was " + expectedScore + " but actual was " + score
806 + " in added request");
807 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900808
Chalard Jean08577fc2018-05-02 21:14:54 +0900809 // Add the request.
Etan Cohenae574a82019-01-08 12:09:18 -0800810 mNetworkRequests.put(request.requestId, request);
Chalard Jean08577fc2018-05-02 21:14:54 +0900811 super.handleAddRequest(request, score, factorySerialNumber);
812 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900813 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400814 }
815
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900816 @Override
817 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900818 synchronized (mExpectations) {
819 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900820
Chalard Jean08577fc2018-05-02 21:14:54 +0900821 assertTrue("Removed more requests than expected", expectedScore != null);
822 // If we're expecting anything, we must be expecting removals.
823 if (mExpectingAdditions) {
824 fail("Can't remove requests while expecting requests to be added");
825 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900826
Chalard Jean08577fc2018-05-02 21:14:54 +0900827 // Remove the request.
Etan Cohenae574a82019-01-08 12:09:18 -0800828 mNetworkRequests.remove(request.requestId);
Chalard Jean08577fc2018-05-02 21:14:54 +0900829 super.handleRemoveRequest(request);
830 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900831 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400832 }
833
Etan Cohenae574a82019-01-08 12:09:18 -0800834 // Trigger releasing the request as unfulfillable
835 public void triggerUnfulfillable(NetworkRequest r) {
836 super.releaseRequestAsUnfulfillableByAnyFactory(r);
837 }
838
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900839 private void assertNoExpectations() {
Chalard Jean08577fc2018-05-02 21:14:54 +0900840 if (mExpectations.size() != 0) {
841 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900842 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400843 }
844
Chalard Jean08577fc2018-05-02 21:14:54 +0900845 // Expects that requests with the specified scores will be added.
846 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900847 assertNoExpectations();
848 mExpectingAdditions = true;
Chalard Jean08577fc2018-05-02 21:14:54 +0900849 for (int score : scores) {
850 mExpectations.add(score);
851 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400852 }
853
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900854 // Expects that count requests will be removed.
855 public void expectRemoveRequests(final int count) {
856 assertNoExpectations();
857 mExpectingAdditions = false;
Chalard Jean08577fc2018-05-02 21:14:54 +0900858 for (int i = 0; i < count; ++i) {
859 mExpectations.add(0); // For removals the score is ignored so any value will do.
860 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900861 }
862
863 // Waits for the expected request additions or removals to happen within a timeout.
864 public void waitForRequests() throws InterruptedException {
Chalard Jean08577fc2018-05-02 21:14:54 +0900865 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
866 synchronized (mExpectations) {
867 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
868 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
869 }
870 }
871 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900872 final String msg = count + " requests still not " +
873 (mExpectingAdditions ? "added" : "removed") +
874 " after " + TIMEOUT_MS + " ms";
875 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900876 }
877
Etan Cohenae574a82019-01-08 12:09:18 -0800878 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
879 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900880 waitForRequests();
881 assertEquals(count, getMyRequestCount());
Etan Cohenae574a82019-01-08 12:09:18 -0800882 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400883 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700884 }
885
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900886 private static Looper startHandlerThreadAndReturnLooper() {
887 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
888 handlerThread.start();
889 return handlerThread.getLooper();
890 }
891
892 private class MockVpn extends Vpn {
893 // TODO : the interactions between this mock and the mock network agent are too
894 // hard to get right at this moment, because it's unclear in which case which
895 // target needs to get a method call or both, and in what order. It's because
896 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
897 // parent class of MockVpn agent wants that responsibility.
898 // That being said inside the test it should be possible to make the interactions
899 // harder to get wrong with precise speccing, judicious comments, helper methods
900 // and a few sprinkled assertions.
901
902 private boolean mConnected = false;
903 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
904 // not inherit from NetworkAgent.
905 private MockNetworkAgent mMockNetworkAgent;
906
907 public MockVpn(int userId) {
908 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
909 userId);
910 }
911
912 public void setNetworkAgent(MockNetworkAgent agent) {
913 waitForIdle(agent, TIMEOUT_MS);
914 mMockNetworkAgent = agent;
915 mNetworkAgent = agent.getNetworkAgent();
916 mNetworkCapabilities.set(agent.getNetworkCapabilities());
917 }
918
919 public void setUids(Set<UidRange> uids) {
920 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800921 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900922 }
923
924 @Override
925 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800926 if (mMockNetworkAgent == null) {
927 return NETID_UNSET;
928 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900929 return mMockNetworkAgent.getNetwork().netId;
930 }
931
932 @Override
933 public boolean appliesToUid(int uid) {
934 return mConnected; // Trickery to simplify testing.
935 }
936
937 @Override
938 protected boolean isCallerEstablishedOwnerLocked() {
939 return mConnected; // Similar trickery
940 }
941
Varun Anandc51b06d2019-02-25 17:22:02 -0800942 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900943 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
944 mConnected = true;
945 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -0800946 mConfig.isMetered = isAlwaysMetered;
947 }
948
949 public void connectAsAlwaysMetered() {
950 connect(true /* isAlwaysMetered */);
951 }
952
953 public void connect() {
954 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900955 }
956
957 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -0800958 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
959 if (!mConnected) return null;
960 super.updateCapabilities(defaultNetwork);
961 // Because super.updateCapabilities will update the capabilities of the agent but
962 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900963 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -0800964 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900965 }
966
967 private void copyCapabilitiesToNetworkAgent() {
968 if (null != mMockNetworkAgent) {
969 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
970 false /* sendToConnectivityService */);
971 }
972 }
973
974 public void disconnect() {
975 mConnected = false;
976 mConfig = null;
977 }
978 }
979
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900980 private class FakeWakeupMessage extends WakeupMessage {
981 private static final int UNREASONABLY_LONG_WAIT = 1000;
982
983 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
984 super(context, handler, cmdName, cmd);
985 }
986
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900987 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
988 int arg1, int arg2, Object obj) {
989 super(context, handler, cmdName, cmd, arg1, arg2, obj);
990 }
991
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900992 @Override
993 public void schedule(long when) {
994 long delayMs = when - SystemClock.elapsedRealtime();
995 if (delayMs < 0) delayMs = 0;
996 if (delayMs > UNREASONABLY_LONG_WAIT) {
997 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
998 "ms into the future: " + delayMs);
999 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001000 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
1001 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001002 }
1003
1004 @Override
1005 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001006 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001007 }
1008
1009 @Override
1010 public void onAlarm() {
1011 throw new AssertionError("Should never happen. Update this fake.");
1012 }
1013 }
1014
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001015 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +09001016 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001017 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -04001018
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001019 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001020 super(c, h, r);
1021 }
1022
1023 @Override
1024 public boolean configRestrictsAvoidBadWifi() {
1025 return configRestrictsAvoidBadWifi;
1026 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001027
1028 @Override
1029 public int configMeteredMultipathPreference() {
1030 return configMeteredMultipathPreference;
1031 }
Erik Kline065ab6e2016-10-02 18:02:14 +09001032 }
1033
1034 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001035 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001036 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +09001037
Paul Jensend7b6ca92015-05-13 14:05:12 -04001038 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001039 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001040 IpConnectivityLog log, INetd netd) {
Hugo Benichif9fdf872016-07-28 17:53:06 +09001041 super(context, netManager, statsService, policyManager, log);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001042 mNetd = netd;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001043 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001044 }
1045
1046 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001047 protected MockableSystemProperties getSystemProperties() {
1048 // Minimal approach to overriding system properties: let most calls fall through to real
1049 // device values, and only override ones values that are important to this test.
1050 mSystemProperties = spy(new MockableSystemProperties());
1051 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1052 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1053 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001054 }
Paul Jensen67b0b072015-06-10 11:22:17 -04001055
1056 @Override
Mike Yuf9729752018-08-17 15:22:05 +08001057 protected Tethering makeTethering() {
1058 return mock(Tethering.class);
1059 }
1060
1061 @Override
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001062 protected ProxyTracker makeProxyTracker() {
1063 return mock(ProxyTracker.class);
1064 }
1065
1066 @Override
Paul Jensen67b0b072015-06-10 11:22:17 -04001067 protected int reserveNetId() {
1068 while (true) {
1069 final int netId = super.reserveNetId();
1070
1071 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1072 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001073 Context context = InstrumentationRegistry.getContext();
1074 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -04001075 boolean overlaps = false;
1076 for (Network network : networks) {
1077 if (netId == network.netId) {
1078 overlaps = true;
1079 break;
1080 }
1081 }
1082 if (overlaps) continue;
1083
1084 return netId;
1085 }
1086 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001087
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001088 @Override
1089 protected boolean queryUserAccess(int uid, int netId) {
1090 return true;
1091 }
1092
junyulai4a192e22018-06-13 15:00:37 +08001093 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1094 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1095 }
1096
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001097 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001098 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +09001099 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001100 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +09001101 return tracker;
1102 }
1103
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001104 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1105 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001106 }
1107
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001108 @Override
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +09001109 protected NetworkStackClient getNetworkStack() {
1110 return mNetworkStack;
1111 }
1112
1113 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +09001114 public WakeupMessage makeWakeupMessage(
1115 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1116 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001117 }
1118
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001119 @Override
1120 public boolean hasService(String name) {
1121 // Currenty, the only relevant service that ConnectivityService checks for is
1122 // ETHERNET_SERVICE.
1123 return Context.ETHERNET_SERVICE.equals(name);
1124 }
1125
Hugo Benichi64901e52017-10-19 14:42:40 +09001126 @Override
1127 protected IpConnectivityMetrics.Logger metricsLogger() {
1128 return mMetricsService;
1129 }
1130
dalyk1fcb7392018-03-05 12:42:22 -05001131 @Override
1132 protected void registerNetdEventCallback() {
1133 }
1134
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001135 public void mockVpn(int uid) {
1136 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001137 int userId = UserHandle.getUserId(uid);
1138 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001139 // This has no effect unless the VPN is actually connected, because things like
1140 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1141 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001142 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001143 }
1144 }
1145
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001146 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001147 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001148 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001149
1150 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001151 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001152 }
Mike Yuf9729752018-08-17 15:22:05 +08001153
1154 public void setUidRulesChanged(int uidRules) {
1155 try {
1156 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1157 } catch (RemoteException ignored) {
1158 }
1159 }
1160
1161 public void setRestrictBackgroundChanged(boolean restrictBackground) {
1162 try {
1163 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1164 } catch (RemoteException ignored) {
1165 }
1166 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001167 }
1168
Paul Jensen3d911462015-06-12 06:40:24 -04001169 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001170 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1171 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001172 */
1173 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001174 if (conditionVariable.block(TIMEOUT_MS)) {
1175 return;
1176 }
1177 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001178 }
1179
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001180 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001181 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001182 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001183
Hugo Benichi64901e52017-10-19 14:42:40 +09001184 MockitoAnnotations.initMocks(this);
1185 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1186
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001187 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1188 // http://b/25897652 .
1189 if (Looper.myLooper() == null) {
1190 Looper.prepare();
1191 }
1192
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001193 FakeSettingsProvider.clearSettingsProvider();
1194 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1195 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001196 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1197 LocalServices.addService(
1198 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001199
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001200 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001201 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001202 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001203 mNpm,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001204 mock(IpConnectivityLog.class),
1205 mMockNetd);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001206
Mike Yuf9729752018-08-17 15:22:05 +08001207 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1208 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1209 verify(mNpm).registerListener(policyListenerCaptor.capture());
1210 mPolicyListener = policyListenerCaptor.getValue();
1211
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001212 // Create local CM before sending system ready so that we can answer
1213 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001214 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001215 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001216 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001217 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001218
1219 // Ensure that the default setting for Captive Portals is used for most tests
1220 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001221 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001222 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001223 }
1224
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001225 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001226 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001227 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001228 if (mCellNetworkAgent != null) {
1229 mCellNetworkAgent.disconnect();
1230 mCellNetworkAgent = null;
1231 }
1232 if (mWiFiNetworkAgent != null) {
1233 mWiFiNetworkAgent.disconnect();
1234 mWiFiNetworkAgent = null;
1235 }
1236 if (mEthernetNetworkAgent != null) {
1237 mEthernetNetworkAgent.disconnect();
1238 mEthernetNetworkAgent = null;
1239 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001240 FakeSettingsProvider.clearSettingsProvider();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001241 }
1242
Hugo Benichibb91c572017-05-22 10:44:02 +09001243 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001244 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001245 case TRANSPORT_ETHERNET:
1246 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001247 case TRANSPORT_WIFI:
1248 return TYPE_WIFI;
1249 case TRANSPORT_CELLULAR:
1250 return TYPE_MOBILE;
1251 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001252 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001253 }
1254 }
1255
1256 private void verifyActiveNetwork(int transport) {
1257 // Test getActiveNetworkInfo()
1258 assertNotNull(mCm.getActiveNetworkInfo());
1259 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1260 // Test getActiveNetwork()
1261 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001262 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001263 if (!NetworkCapabilities.isValidTransport(transport)) {
1264 throw new IllegalStateException("Unknown transport " + transport);
1265 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001266 switch (transport) {
1267 case TRANSPORT_WIFI:
1268 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1269 break;
1270 case TRANSPORT_CELLULAR:
1271 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1272 break;
1273 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001274 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001275 }
1276 // Test getNetworkInfo(Network)
1277 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001278 assertEquals(transportToLegacyType(transport),
1279 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001280 // Test getNetworkCapabilities(Network)
1281 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1282 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1283 }
1284
1285 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001286 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001287 // Test getActiveNetworkInfo()
1288 assertNull(mCm.getActiveNetworkInfo());
1289 // Test getActiveNetwork()
1290 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001291 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001292 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001293 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001294 }
1295
1296 /**
1297 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1298 * broadcasts are received.
1299 */
1300 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1301 final ConditionVariable cv = new ConditionVariable();
1302 mServiceContext.registerReceiver(new BroadcastReceiver() {
1303 private int remaining = count;
1304 public void onReceive(Context context, Intent intent) {
1305 if (--remaining == 0) {
1306 cv.open();
1307 mServiceContext.unregisterReceiver(this);
1308 }
1309 }
1310 }, new IntentFilter(CONNECTIVITY_ACTION));
1311 return cv;
1312 }
1313
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001314 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001315 public void testNetworkTypes() {
1316 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1317 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1318 // will fail. Failing here is much easier to debug.
1319 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1320 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001321 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1322 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1323
1324 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1325 // mocks, this assert exercises the ConnectivityService code path that ensures that
1326 // TYPE_ETHERNET is supported if the ethernet service is running.
1327 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001328 }
1329
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001330 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001331 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001332 verifyNoNetwork();
1333 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1334 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1335 assertNull(mCm.getActiveNetworkInfo());
1336 assertNull(mCm.getActiveNetwork());
1337 // Test bringing up validated cellular.
1338 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1339 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001340 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001341 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001342 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001343 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1344 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1345 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1346 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1347 // Test bringing up validated WiFi.
1348 cv = waitForConnectivityBroadcasts(2);
1349 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001350 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001351 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001352 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001353 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1354 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1355 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1356 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1357 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001358 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001359 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001360 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001361 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001362 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001363 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1364 // Test WiFi disconnect.
1365 cv = waitForConnectivityBroadcasts(1);
1366 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001367 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001368 verifyNoNetwork();
1369 }
1370
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001371 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001372 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1373 // Test bringing up unvalidated WiFi
1374 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1375 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1376 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001377 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001378 verifyActiveNetwork(TRANSPORT_WIFI);
1379 // Test bringing up unvalidated cellular
1380 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1381 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001382 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001383 verifyActiveNetwork(TRANSPORT_WIFI);
1384 // Test cellular disconnect.
1385 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001386 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001387 verifyActiveNetwork(TRANSPORT_WIFI);
1388 // Test bringing up validated cellular
1389 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1390 cv = waitForConnectivityBroadcasts(2);
1391 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001392 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001393 verifyActiveNetwork(TRANSPORT_CELLULAR);
1394 // Test cellular disconnect.
1395 cv = waitForConnectivityBroadcasts(2);
1396 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001397 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001398 verifyActiveNetwork(TRANSPORT_WIFI);
1399 // Test WiFi disconnect.
1400 cv = waitForConnectivityBroadcasts(1);
1401 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001402 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001403 verifyNoNetwork();
1404 }
1405
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001406 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001407 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1408 // Test bringing up unvalidated cellular.
1409 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1410 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1411 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001412 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001413 verifyActiveNetwork(TRANSPORT_CELLULAR);
1414 // Test bringing up unvalidated WiFi.
1415 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1416 cv = waitForConnectivityBroadcasts(2);
1417 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001418 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001419 verifyActiveNetwork(TRANSPORT_WIFI);
1420 // Test WiFi disconnect.
1421 cv = waitForConnectivityBroadcasts(2);
1422 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001423 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001424 verifyActiveNetwork(TRANSPORT_CELLULAR);
1425 // Test cellular disconnect.
1426 cv = waitForConnectivityBroadcasts(1);
1427 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001428 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001429 verifyNoNetwork();
1430 }
1431
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001432 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001433 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001434 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001435 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001436 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1437 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001438 waitFor(cv);
1439 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001440 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001441 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001442 // Test bringing up validated cellular.
1443 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001444 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001445 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001446 waitFor(cv);
1447 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001448 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1449 NET_CAPABILITY_VALIDATED));
1450 // Test cellular disconnect.
1451 cv = waitForConnectivityBroadcasts(2);
1452 mCellNetworkAgent.disconnect();
1453 waitFor(cv);
1454 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001455 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001456 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001457 NET_CAPABILITY_VALIDATED));
1458 }
1459
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001460 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001461 public void testCellularOutscoresWeakWifi() throws Exception {
1462 // Test bringing up validated cellular.
1463 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1464 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1465 mCellNetworkAgent.connect(true);
1466 waitFor(cv);
1467 verifyActiveNetwork(TRANSPORT_CELLULAR);
1468 // Test bringing up validated WiFi.
1469 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1470 cv = waitForConnectivityBroadcasts(2);
1471 mWiFiNetworkAgent.connect(true);
1472 waitFor(cv);
1473 verifyActiveNetwork(TRANSPORT_WIFI);
1474 // Test WiFi getting really weak.
1475 cv = waitForConnectivityBroadcasts(2);
1476 mWiFiNetworkAgent.adjustScore(-11);
1477 waitFor(cv);
1478 verifyActiveNetwork(TRANSPORT_CELLULAR);
1479 // Test WiFi restoring signal strength.
1480 cv = waitForConnectivityBroadcasts(2);
1481 mWiFiNetworkAgent.adjustScore(11);
1482 waitFor(cv);
1483 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001484 }
1485
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001486 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001487 public void testReapingNetwork() throws Exception {
1488 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1489 // Expect it to be torn down immediately because it satisfies no requests.
1490 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1491 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1492 mWiFiNetworkAgent.connectWithoutInternet();
1493 waitFor(cv);
1494 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1495 // Expect it to be torn down immediately because it satisfies no requests.
1496 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1497 cv = mCellNetworkAgent.getDisconnectedCV();
1498 mCellNetworkAgent.connectWithoutInternet();
1499 waitFor(cv);
1500 // Test bringing up validated WiFi.
1501 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1502 cv = waitForConnectivityBroadcasts(1);
1503 mWiFiNetworkAgent.connect(true);
1504 waitFor(cv);
1505 verifyActiveNetwork(TRANSPORT_WIFI);
1506 // Test bringing up unvalidated cellular.
1507 // Expect it to be torn down because it could never be the highest scoring network
1508 // satisfying the default request even if it validated.
1509 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1510 cv = mCellNetworkAgent.getDisconnectedCV();
1511 mCellNetworkAgent.connect(false);
1512 waitFor(cv);
1513 verifyActiveNetwork(TRANSPORT_WIFI);
1514 cv = mWiFiNetworkAgent.getDisconnectedCV();
1515 mWiFiNetworkAgent.disconnect();
1516 waitFor(cv);
1517 }
1518
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001519 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001520 public void testCellularFallback() throws Exception {
1521 // Test bringing up validated cellular.
1522 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1523 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1524 mCellNetworkAgent.connect(true);
1525 waitFor(cv);
1526 verifyActiveNetwork(TRANSPORT_CELLULAR);
1527 // Test bringing up validated WiFi.
1528 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1529 cv = waitForConnectivityBroadcasts(2);
1530 mWiFiNetworkAgent.connect(true);
1531 waitFor(cv);
1532 verifyActiveNetwork(TRANSPORT_WIFI);
1533 // Reevaluate WiFi (it'll instantly fail DNS).
1534 cv = waitForConnectivityBroadcasts(2);
1535 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1536 NET_CAPABILITY_VALIDATED));
1537 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1538 // Should quickly fall back to Cellular.
1539 waitFor(cv);
1540 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1541 NET_CAPABILITY_VALIDATED));
1542 verifyActiveNetwork(TRANSPORT_CELLULAR);
1543 // Reevaluate cellular (it'll instantly fail DNS).
1544 cv = waitForConnectivityBroadcasts(2);
1545 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1546 NET_CAPABILITY_VALIDATED));
1547 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1548 // Should quickly fall back to WiFi.
1549 waitFor(cv);
1550 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1551 NET_CAPABILITY_VALIDATED));
1552 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1553 NET_CAPABILITY_VALIDATED));
1554 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001555 }
1556
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001557 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001558 public void testWiFiFallback() throws Exception {
1559 // Test bringing up unvalidated WiFi.
1560 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1561 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1562 mWiFiNetworkAgent.connect(false);
1563 waitFor(cv);
1564 verifyActiveNetwork(TRANSPORT_WIFI);
1565 // Test bringing up validated cellular.
1566 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1567 cv = waitForConnectivityBroadcasts(2);
1568 mCellNetworkAgent.connect(true);
1569 waitFor(cv);
1570 verifyActiveNetwork(TRANSPORT_CELLULAR);
1571 // Reevaluate cellular (it'll instantly fail DNS).
1572 cv = waitForConnectivityBroadcasts(2);
1573 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1574 NET_CAPABILITY_VALIDATED));
1575 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1576 // Should quickly fall back to WiFi.
1577 waitFor(cv);
1578 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1579 NET_CAPABILITY_VALIDATED));
1580 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001581 }
1582
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001583 @Test
1584 public void testRequiresValidation() {
1585 assertTrue(NetworkMonitorUtils.isValidationRequired(
1586 mCm.getDefaultRequest().networkCapabilities));
1587 }
1588
Paul Jensen3d911462015-06-12 06:40:24 -04001589 enum CallbackState {
1590 NONE,
1591 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001592 NETWORK_CAPABILITIES,
1593 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001594 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001595 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001596 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001597 LOST,
Mike Yuf9729752018-08-17 15:22:05 +08001598 UNAVAILABLE,
1599 BLOCKED_STATUS
Paul Jensen3d911462015-06-12 06:40:24 -04001600 }
1601
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001602 private static class CallbackInfo {
1603 public final CallbackState state;
1604 public final Network network;
1605 public final Object arg;
1606 public CallbackInfo(CallbackState s, Network n, Object o) {
1607 state = s; network = n; arg = o;
1608 }
1609 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001610 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001611 }
1612 @Override
1613 public boolean equals(Object o) {
1614 if (!(o instanceof CallbackInfo)) return false;
1615 // Ignore timeMs, since it's unpredictable.
1616 CallbackInfo other = (CallbackInfo) o;
1617 return (state == other.state) && Objects.equals(network, other.network);
1618 }
1619 @Override
1620 public int hashCode() {
1621 return Objects.hash(state, network);
1622 }
1623 }
1624
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001625 /**
1626 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1627 * this class receives, by calling expectCallback() exactly once each time a callback is
1628 * received. assertNoCallback may be called at any time.
1629 */
Paul Jensen3d911462015-06-12 06:40:24 -04001630 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001631 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001632 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001633
Erik Klineacdd6392016-07-07 16:50:58 +09001634 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001635 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001636 }
Paul Jensen3d911462015-06-12 06:40:24 -04001637
Erik Klineacdd6392016-07-07 16:50:58 +09001638 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001639 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001640 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001641 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001642 }
1643
Erik Klineacdd6392016-07-07 16:50:58 +09001644 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001645 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1646 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1647 }
1648
1649 @Override
1650 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1651 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1652 }
1653
1654 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001655 public void onUnavailable() {
1656 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1657 }
1658
1659 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001660 public void onNetworkSuspended(Network network) {
1661 setLastCallback(CallbackState.SUSPENDED, network, null);
1662 }
1663
1664 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001665 public void onNetworkResumed(Network network) {
1666 setLastCallback(CallbackState.RESUMED, network, null);
1667 }
1668
1669 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001670 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001671 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001672 }
1673
Erik Klineacdd6392016-07-07 16:50:58 +09001674 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001675 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001676 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001677 setLastCallback(CallbackState.LOST, network, null);
1678 }
1679
Mike Yuf9729752018-08-17 15:22:05 +08001680 @Override
1681 public void onBlockedStatusChanged(Network network, boolean blocked) {
1682 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1683 }
1684
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001685 public Network getLastAvailableNetwork() {
1686 return mLastAvailableNetwork;
1687 }
1688
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001689 CallbackInfo nextCallback(int timeoutMs) {
1690 CallbackInfo cb = null;
1691 try {
1692 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1693 } catch (InterruptedException e) {
1694 }
1695 if (cb == null) {
1696 // LinkedBlockingQueue.poll() returns null if it timeouts.
1697 fail("Did not receive callback after " + timeoutMs + "ms");
1698 }
1699 return cb;
1700 }
1701
Erik Kline1d3db322017-02-28 16:20:20 +09001702 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1703 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1704 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001705 CallbackInfo actual = nextCallback(timeoutMs);
1706 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001707
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001708 if (state == CallbackState.LOSING) {
1709 String msg = String.format(
1710 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001711 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001712 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001713 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001714 }
Erik Kline1d3db322017-02-28 16:20:20 +09001715
1716 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001717 }
1718
Erik Kline1d3db322017-02-28 16:20:20 +09001719 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001720 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001721 }
1722
Hugo Benichi16f0a942017-06-20 14:07:59 +09001723 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001724 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09001725 }
1726
1727 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1728 int timeLeft = timeoutMs;
1729 while (timeLeft > 0) {
1730 long start = SystemClock.elapsedRealtime();
1731 CallbackInfo info = nextCallback(timeLeft);
1732 if (fn.test(info)) {
1733 return info;
1734 }
1735 timeLeft -= (SystemClock.elapsedRealtime() - start);
1736 }
1737 fail("Did not receive expected callback after " + timeoutMs + "ms");
1738 return null;
1739 }
1740
Lorenzo Colitti27334542018-01-12 16:22:21 +09001741 // Expects onAvailable and the callbacks that follow it. These are:
1742 // - onSuspended, iff the network was suspended when the callbacks fire.
1743 // - onCapabilitiesChanged.
1744 // - onLinkPropertiesChanged.
Mike Yuf9729752018-08-17 15:22:05 +08001745 // - onBlockedStatusChanged.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001746 //
1747 // @param agent the network to expect the callbacks on.
1748 // @param expectSuspended whether to expect a SUSPENDED callback.
1749 // @param expectValidated the expected value of the VALIDATED capability in the
1750 // onCapabilitiesChanged callback.
1751 // @param timeoutMs how long to wait for the callbacks.
1752 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
Mike Yuf9729752018-08-17 15:22:05 +08001753 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001754 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001755 if (expectSuspended) {
1756 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001757 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001758 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001759 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001760 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001761 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001762 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001763 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Mike Yuf9729752018-08-17 15:22:05 +08001764 expectBlockedStatusCallback(expectBlocked, agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001765 }
1766
Lorenzo Colitti27334542018-01-12 16:22:21 +09001767 // Expects the available callbacks (validated), plus onSuspended.
1768 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
Mike Yuf9729752018-08-17 15:22:05 +08001769 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001770 }
1771
Lorenzo Colitti27334542018-01-12 16:22:21 +09001772 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001773 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1774 }
1775
1776 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1777 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001778 }
1779
Lorenzo Colitti27334542018-01-12 16:22:21 +09001780 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001781 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1782 }
1783
1784 void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1785 expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001786 }
1787
1788 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1789 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1790 // one we just sent.
1791 // TODO: this is likely a bug. Fix it and remove this method.
1792 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001793 expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001794 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001795 expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
Mike Yuf9729752018-08-17 15:22:05 +08001796 // Implicitly check the network is allowed to use.
1797 // TODO: should we need to consider if network is in blocked status in this case?
1798 expectBlockedStatusCallback(false, agent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001799 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1800 assertEquals(nc1, nc2);
1801 }
1802
1803 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1804 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1805 // when a network connects and satisfies a callback, and then immediately validates.
1806 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1807 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001808 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1809 }
1810
Lorenzo Colitti27334542018-01-12 16:22:21 +09001811 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001812 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001813 }
1814
1815 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1816 int timeoutMs) {
1817 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001818 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1819 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001820 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001821 }
1822
Lorenzo Colitti27334542018-01-12 16:22:21 +09001823 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001824 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001825 }
1826
1827 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1828 int timeoutMs) {
1829 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001830 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1831 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001832 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001833 }
1834
Chalard Jean0b214af2018-01-12 17:22:49 +09001835 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1836 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001837 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1838 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001839 }
1840
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09001841 void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1842 CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1843 assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1844 fn.test((LinkProperties) cbi.arg));
1845 }
1846
Mike Yuf9729752018-08-17 15:22:05 +08001847 void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1848 CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1849 boolean actualBlocked = (boolean) cbi.arg;
1850 assertEquals(expectBlocked, actualBlocked);
1851 }
1852
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001853 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001854 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001855 CallbackInfo c = mCallbacks.peek();
1856 assertNull("Unexpected callback: " + c, c);
1857 }
1858 }
1859
1860 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1861 // only be declared in a static or top level type".
1862 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1863 for (TestNetworkCallback c : callbacks) {
1864 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001865 }
1866 }
1867
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001868 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001869 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001870 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001871 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1872 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001873 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1874 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001875 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1876 .addTransportType(TRANSPORT_WIFI).build();
1877 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1878 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001879 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001880 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1881 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1882
1883 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001884 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1885 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1886 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001887 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1888 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001889 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1890 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001891 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001892
Paul Jensen3d911462015-06-12 06:40:24 -04001893 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1894 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001895 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001896 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001897 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1898
Paul Jensen3d911462015-06-12 06:40:24 -04001899 cv = waitForConnectivityBroadcasts(2);
1900 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1901 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001902 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1903 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001904 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1905 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001906 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001907
Paul Jensen3d911462015-06-12 06:40:24 -04001908 cv = waitForConnectivityBroadcasts(2);
1909 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001910 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1911 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001912 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001913 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001914 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001915
Paul Jensen3d911462015-06-12 06:40:24 -04001916 cv = waitForConnectivityBroadcasts(1);
1917 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001918 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1919 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001920 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001921 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001922
1923 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04001924 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1925 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001926 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1927 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001928 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001929 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001930
Paul Jensen3d911462015-06-12 06:40:24 -04001931 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1932 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001933 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001934 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001935 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1936
Paul Jensen3d911462015-06-12 06:40:24 -04001937 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1938 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001939 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001940 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001941 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001942 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001943 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001944 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001945 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001946
Paul Jensen3d911462015-06-12 06:40:24 -04001947 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001948 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1949 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
1950 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001951
Paul Jensen3d911462015-06-12 06:40:24 -04001952 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001953 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1954 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
1955 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001956 }
1957
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001958 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001959 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001960 // This test would be flaky with the default 120ms timer: that is short enough that
1961 // lingered networks are torn down before assertions can be run. We don't want to mock the
1962 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1963 // in detecting races.
1964 mService.mLingerDelayMs = 300;
1965
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001966 NetworkRequest request = new NetworkRequest.Builder()
1967 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1968 .build();
1969 TestNetworkCallback callback = new TestNetworkCallback();
1970 mCm.registerNetworkCallback(request, callback);
1971
1972 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1973 mCm.registerDefaultNetworkCallback(defaultCallback);
1974
1975 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1976 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1977 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
1978
1979 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1980 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1981 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1982
1983 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001984 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1985 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001986 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001987 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001988
1989 mWiFiNetworkAgent.connect(true);
1990 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1991 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001992 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001993 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001994 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001995 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001996 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001997 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001998 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001999
2000 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002001 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002002 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002003 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002004 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002005 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002006 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002007 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002008
2009 mEthernetNetworkAgent.disconnect();
2010 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2011 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002012 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002013 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002014
2015 for (int i = 0; i < 4; i++) {
2016 MockNetworkAgent oldNetwork, newNetwork;
2017 if (i % 2 == 0) {
2018 mWiFiNetworkAgent.adjustScore(-15);
2019 oldNetwork = mWiFiNetworkAgent;
2020 newNetwork = mCellNetworkAgent;
2021 } else {
2022 mWiFiNetworkAgent.adjustScore(15);
2023 oldNetwork = mCellNetworkAgent;
2024 newNetwork = mWiFiNetworkAgent;
2025
2026 }
2027 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002028 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2029 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002030 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002031 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2032 }
2033 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2034
2035 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2036 // if the network is still up.
2037 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002038 // We expect a notification about the capabilities change, and nothing else.
2039 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2040 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002041 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002042 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002043
2044 // Wifi no longer satisfies our listen, which is for an unmetered network.
2045 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002046 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2047
2048 // Disconnect our test networks.
2049 mWiFiNetworkAgent.disconnect();
2050 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002051 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002052 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002053 mCellNetworkAgent.disconnect();
2054 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002055 waitForIdle();
2056 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002057
2058 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002059 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002060
2061 // Check that a network is only lingered or torn down if it would not satisfy a request even
2062 // if it validated.
2063 request = new NetworkRequest.Builder().clearCapabilities().build();
2064 callback = new TestNetworkCallback();
2065
2066 mCm.registerNetworkCallback(request, callback);
2067
2068 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2069 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002070 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2071 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002072 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002073 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002074
2075 // Bring up wifi with a score of 20.
2076 // Cell stays up because it would satisfy the default request if it validated.
2077 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2078 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002079 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2080 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002081 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002082 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002083
2084 mWiFiNetworkAgent.disconnect();
2085 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2086 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002087 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002088 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002089 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002090
2091 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002092 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002093 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2094 mWiFiNetworkAgent.adjustScore(50);
2095 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002096 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002097 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002098 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002099 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002100 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002101
2102 // Tear down wifi.
2103 mWiFiNetworkAgent.disconnect();
2104 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2105 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002106 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002107 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002108 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002109
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002110 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2111 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002112 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2113 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002114 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002115 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002116 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002117 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002118 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002119 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002120 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002121
2122 mWiFiNetworkAgent.disconnect();
2123 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002124 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002125 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002126 mCellNetworkAgent.disconnect();
2127 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2128 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002129 waitForIdle();
2130 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002131
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002132 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002133 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2134 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002135 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2136 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002137 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002138 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2139 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002140 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2141 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002142 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002143 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002144 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002145 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002146
2147 NetworkRequest cellRequest = new NetworkRequest.Builder()
2148 .addTransportType(TRANSPORT_CELLULAR).build();
2149 NetworkCallback noopCallback = new NetworkCallback();
2150 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002151 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2152 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002153 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002154 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002155
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002156 // Similar to the above: lingering can start even after the lingered request is removed.
2157 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002158 mWiFiNetworkAgent.disconnect();
2159 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002160 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002161 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002162 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002163
2164 // Cell is now the default network. Pin it with a cell-specific request.
2165 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2166 mCm.requestNetwork(cellRequest, noopCallback);
2167
2168 // Now connect wifi, and expect it to become the default network.
2169 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2170 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002171 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2172 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002173 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002174 // The default request is lingering on cell, but nothing happens to cell, and we send no
2175 // callbacks for it, because it's kept up by cellRequest.
2176 callback.assertNoCallback();
2177 // Now unregister cellRequest and expect cell to start lingering.
2178 mCm.unregisterNetworkCallback(noopCallback);
2179 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2180
2181 // Let linger run its course.
2182 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002183 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002184 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002185
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002186 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2187 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2188 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002189 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002190 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2191 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002192 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002193 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2194 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002195 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2196 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002197 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002198
2199 // Let linger run its course.
2200 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2201
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002202 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002203 mEthernetNetworkAgent.disconnect();
2204 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2205 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2206 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002207
2208 mCm.unregisterNetworkCallback(callback);
2209 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002210 mCm.unregisterNetworkCallback(trackDefaultCallback);
2211 }
2212
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002213 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002214 public void testNetworkGoesIntoBackgroundAfterLinger() {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002215 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002216 NetworkRequest request = new NetworkRequest.Builder()
2217 .clearCapabilities()
2218 .build();
2219 TestNetworkCallback callback = new TestNetworkCallback();
2220 mCm.registerNetworkCallback(request, callback);
2221
2222 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2223 mCm.registerDefaultNetworkCallback(defaultCallback);
2224
2225 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2226 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2227
2228 mCellNetworkAgent.connect(true);
2229 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2230 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2231
2232 // Wifi comes up and cell lingers.
2233 mWiFiNetworkAgent.connect(true);
2234 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2235 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2236 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2237 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2238
2239 // File a request for cellular, then release it.
2240 NetworkRequest cellRequest = new NetworkRequest.Builder()
2241 .addTransportType(TRANSPORT_CELLULAR).build();
2242 NetworkCallback noopCallback = new NetworkCallback();
2243 mCm.requestNetwork(cellRequest, noopCallback);
2244 mCm.unregisterNetworkCallback(noopCallback);
2245 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2246
2247 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002248 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002249 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2250 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2251 lingerTimeoutMs);
2252
2253 // Clean up.
2254 mCm.unregisterNetworkCallback(defaultCallback);
2255 mCm.unregisterNetworkCallback(callback);
2256 }
2257
2258 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002259 public void testExplicitlySelected() {
2260 NetworkRequest request = new NetworkRequest.Builder()
2261 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2262 .build();
2263 TestNetworkCallback callback = new TestNetworkCallback();
2264 mCm.registerNetworkCallback(request, callback);
2265
2266 // Bring up validated cell.
2267 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2268 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002269 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002270
2271 // Bring up unvalidated wifi with explicitlySelected=true.
2272 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2273 mWiFiNetworkAgent.explicitlySelected(false);
2274 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002275 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002276
2277 // Cell Remains the default.
2278 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2279
2280 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2281 // it's explicitly selected.
2282 mWiFiNetworkAgent.adjustScore(-40);
2283 mWiFiNetworkAgent.adjustScore(40);
2284 callback.assertNoCallback();
2285
2286 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2287 // wifi even though it's unvalidated.
2288 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2289 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2290 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2291
2292 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2293 mWiFiNetworkAgent.disconnect();
2294 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2295 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2296 mWiFiNetworkAgent.explicitlySelected(false);
2297 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002298 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002299
2300 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2301 // network to disconnect.
2302 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2303 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2304
2305 // Reconnect, again with explicitlySelected=true, but this time validate.
2306 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2307 mWiFiNetworkAgent.explicitlySelected(false);
2308 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002309 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002310 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2311 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2312 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2313
2314 // BUG: the network will no longer linger, even though it's validated and outscored.
2315 // TODO: fix this.
2316 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2317 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002318 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002319 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2320 callback.assertNoCallback();
2321
2322 // Clean up.
2323 mWiFiNetworkAgent.disconnect();
2324 mCellNetworkAgent.disconnect();
2325 mEthernetNetworkAgent.disconnect();
2326
2327 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2328 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2329 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002330 }
2331
Chalard Jean08577fc2018-05-02 21:14:54 +09002332 private int[] makeIntArray(final int size, final int value) {
2333 final int[] array = new int[size];
2334 Arrays.fill(array, value);
2335 return array;
2336 }
2337
Paul Jensen85cf78e2015-06-25 13:25:07 -04002338 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002339 // Verify NOT_RESTRICTED is set appropriately
2340 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2341 .build().networkCapabilities;
2342 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2343 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2344 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002345 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002346 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2347 } else {
2348 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2349 }
2350
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002351 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002352 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002353 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2354 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002355 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002356 mServiceContext, "testFactory", filter);
2357 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002358 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean08577fc2018-05-02 21:14:54 +09002359 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002360 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002361 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002362 int expectedRequestCount = 1;
2363 NetworkCallback networkCallback = null;
2364 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2365 // add one.
2366 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002367 assertFalse(testFactory.getMyStartRequested());
2368 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2369 networkCallback = new NetworkCallback();
Chalard Jean08577fc2018-05-02 21:14:54 +09002370 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002371 mCm.requestNetwork(request, networkCallback);
2372 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002373 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002374 }
Paul Jensen3d911462015-06-12 06:40:24 -04002375 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002376 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2377 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002378
Paul Jensen85cf78e2015-06-25 13:25:07 -04002379 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002380 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002381 // Rather than create a validated network which complicates things by registering it's
2382 // own NetworkRequest during startup, just bump up the score to cancel out the
2383 // unvalidated penalty.
2384 testAgent.adjustScore(40);
2385 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002386
2387 // When testAgent connects, ConnectivityService will re-send us all current requests with
2388 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2389 // them.
Chalard Jean08577fc2018-05-02 21:14:54 +09002390 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002391 testAgent.connect(false);
2392 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002393 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002394 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002395 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002396
Paul Jensen85cf78e2015-06-25 13:25:07 -04002397 // Bring in a bunch of requests.
Chalard Jean08577fc2018-05-02 21:14:54 +09002398 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002399 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002400 ConnectivityManager.NetworkCallback[] networkCallbacks =
2401 new ConnectivityManager.NetworkCallback[10];
2402 for (int i = 0; i< networkCallbacks.length; i++) {
2403 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2404 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002405 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002406 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2407 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002408 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2409 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002410
Paul Jensen85cf78e2015-06-25 13:25:07 -04002411 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002412 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002413 for (int i = 0; i < networkCallbacks.length; i++) {
2414 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2415 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002416 testFactory.waitForNetworkRequests(expectedRequestCount);
2417 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002418
Paul Jensen85cf78e2015-06-25 13:25:07 -04002419 // Drop the higher scored network.
2420 cv = testFactory.getNetworkStartedCV();
Chalard Jean08577fc2018-05-02 21:14:54 +09002421 // With the default network disconnecting, the requests are sent with score 0 to factories.
2422 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002423 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002424 waitFor(cv);
Chalard Jean08577fc2018-05-02 21:14:54 +09002425 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002426 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2427 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002428
2429 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002430 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002431 handlerThread.quit();
2432 }
2433
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002434 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002435 public void testNetworkFactoryRequests() throws Exception {
2436 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2437 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2438 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2439 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2440 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2441 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2442 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2443 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2444 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2445 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2446 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2447 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2448 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2449 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2450 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2451 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2452 }
2453
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002454 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002455 public void testNoMutableNetworkRequests() throws Exception {
2456 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002457 NetworkRequest request1 = new NetworkRequest.Builder()
2458 .addCapability(NET_CAPABILITY_VALIDATED)
2459 .build();
2460 NetworkRequest request2 = new NetworkRequest.Builder()
2461 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2462 .build();
2463
2464 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2465 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2466 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2467 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2468 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002469 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002470
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002471 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002472 public void testMMSonWiFi() throws Exception {
2473 // Test bringing up cellular without MMS NetworkRequest gets reaped
2474 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2475 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2476 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2477 mCellNetworkAgent.connectWithoutInternet();
2478 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002479 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002480 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002481 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002482
Paul Jensene0988542015-06-25 15:30:08 -04002483 // Test bringing up validated WiFi.
2484 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2485 cv = waitForConnectivityBroadcasts(1);
2486 mWiFiNetworkAgent.connect(true);
2487 waitFor(cv);
2488 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002489
Paul Jensene0988542015-06-25 15:30:08 -04002490 // Register MMS NetworkRequest
2491 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2492 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2493 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2494 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002495
Paul Jensene0988542015-06-25 15:30:08 -04002496 // Test bringing up unvalidated cellular with MMS
2497 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2498 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002499 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002500 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002501 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002502
Paul Jensene0988542015-06-25 15:30:08 -04002503 // Test releasing NetworkRequest disconnects cellular with MMS
2504 cv = mCellNetworkAgent.getDisconnectedCV();
2505 mCm.unregisterNetworkCallback(networkCallback);
2506 waitFor(cv);
2507 verifyActiveNetwork(TRANSPORT_WIFI);
2508 }
2509
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002510 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002511 public void testMMSonCell() throws Exception {
2512 // Test bringing up cellular without MMS
2513 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2514 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2515 mCellNetworkAgent.connect(false);
2516 waitFor(cv);
2517 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002518
Paul Jensene0988542015-06-25 15:30:08 -04002519 // Register MMS NetworkRequest
2520 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2521 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2522 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2523 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002524
Paul Jensene0988542015-06-25 15:30:08 -04002525 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002526 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2527 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2528 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002529 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002530 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002531
Paul Jensene0988542015-06-25 15:30:08 -04002532 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2533 cv = mmsNetworkAgent.getDisconnectedCV();
2534 mCm.unregisterNetworkCallback(networkCallback);
2535 waitFor(cv);
2536 verifyActiveNetwork(TRANSPORT_CELLULAR);
2537 }
2538
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002539 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002540 public void testCaptivePortal() {
2541 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2542 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2543 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2544 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2545
2546 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2547 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2548 .addCapability(NET_CAPABILITY_VALIDATED).build();
2549 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002550
2551 // Bring up a network with a captive portal.
2552 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002553 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002554 String firstRedirectUrl = "http://example.com/firstPath";
2555 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002556 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002557 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002558
2559 // Take down network.
2560 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002561 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002562 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002563
2564 // Bring up a network with a captive portal.
2565 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002566 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002567 String secondRedirectUrl = "http://example.com/secondPath";
2568 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002569 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002570 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002571
2572 // Make captive portal disappear then revalidate.
2573 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002574 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002575 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002576 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002577
2578 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002579 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002580
2581 // Break network connectivity.
2582 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002583 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002584 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002585 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002586 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002587
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002588 @Test
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002589 public void testCaptivePortalApp() throws RemoteException {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002590 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2591 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2592 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2593 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2594
2595 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2596 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2597 .addCapability(NET_CAPABILITY_VALIDATED).build();
2598 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2599
2600 // Bring up wifi.
2601 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2602 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002603 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002604 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2605
2606 // Check that calling startCaptivePortalApp does nothing.
2607 final int fastTimeoutMs = 100;
2608 mCm.startCaptivePortalApp(wifiNetwork);
2609 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2610
2611 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002612 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002613 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002614 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002615 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2616
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002617 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002618 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002619 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2620 .launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002621
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002622 // Report that the captive portal is dismissed, and check that callbacks are fired
2623 mWiFiNetworkAgent.setNetworkValid();
2624 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002625 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002626 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2627
2628 mCm.unregisterNetworkCallback(validatedCallback);
2629 mCm.unregisterNetworkCallback(captivePortalCallback);
2630 }
2631
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002632 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002633 public void testAvoidOrIgnoreCaptivePortals() {
2634 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2635 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2636 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2637 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2638
2639 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2640 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2641 .addCapability(NET_CAPABILITY_VALIDATED).build();
2642 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2643
2644 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2645 // Bring up a network with a captive portal.
2646 // Expect it to fail to connect and not result in any callbacks.
2647 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2648 String firstRedirectUrl = "http://example.com/firstPath";
2649
2650 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2651 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2652 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2653 waitFor(disconnectCv);
2654 waitFor(avoidCv);
2655
2656 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002657 }
2658
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002659 private NetworkRequest.Builder newWifiRequestBuilder() {
2660 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2661 }
2662
Etan Cohen836ad572018-12-30 17:59:59 -08002663 /**
2664 * Verify request matching behavior with network specifiers.
2665 *
2666 * Note: this test is somewhat problematic since it involves removing capabilities from
2667 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2668 * as a WTF bug in
2669 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2670 * does work.
2671 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002672 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002673 public void testNetworkSpecifier() {
Etan Cohen836ad572018-12-30 17:59:59 -08002674 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2675 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2676 Parcelable {
2677 @Override
2678 public boolean satisfiedBy(NetworkSpecifier other) {
2679 return true;
2680 }
2681
2682 @Override
2683 public int describeContents() {
2684 return 0;
2685 }
2686
2687 @Override
2688 public void writeToParcel(Parcel dest, int flags) {}
2689
2690 @Override
2691 public NetworkSpecifier redact() {
2692 return null;
2693 }
2694 }
2695
2696 // A network specifier that matches either another LocalNetworkSpecifier with the same
2697 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2698 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2699 private String mString;
2700
2701 LocalStringNetworkSpecifier(String string) {
2702 mString = string;
2703 }
2704
2705 @Override
2706 public boolean satisfiedBy(NetworkSpecifier other) {
2707 if (other instanceof LocalStringNetworkSpecifier) {
2708 return TextUtils.equals(mString,
2709 ((LocalStringNetworkSpecifier) other).mString);
2710 }
2711 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2712 return false;
2713 }
2714
2715 @Override
2716 public int describeContents() {
2717 return 0;
2718 }
2719 @Override
2720 public void writeToParcel(Parcel dest, int flags) {}
2721 }
2722
2723
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002724 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002725 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002726 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002727 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2728 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002729 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2730 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002731 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002732 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002733
2734 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2735 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2736 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002737 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002738 TestNetworkCallback cFoo = new TestNetworkCallback();
2739 TestNetworkCallback cBar = new TestNetworkCallback();
2740 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002741 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002742
2743 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2744 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2745 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002746 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002747 mCm.registerNetworkCallback(rFoo, cFoo);
2748 mCm.registerNetworkCallback(rBar, cBar);
2749
Etan Cohen836ad572018-12-30 17:59:59 -08002750 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2751 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2752
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002753 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2754 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002755 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2756 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2757 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2758 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002759 assertNoCallbacks(cFoo, cBar);
2760
Etan Cohen836ad572018-12-30 17:59:59 -08002761 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002762 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002763 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002764 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2765 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002766 }
Etan Cohen836ad572018-12-30 17:59:59 -08002767 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
2768 mWiFiNetworkAgent);
2769 assertEquals(nsFoo,
2770 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002771 cFoo.assertNoCallback();
2772
Etan Cohen836ad572018-12-30 17:59:59 -08002773 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002774 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002775 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002776 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08002777 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2778 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002779 }
Etan Cohen836ad572018-12-30 17:59:59 -08002780 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
2781 mWiFiNetworkAgent);
2782 assertEquals(nsBar,
2783 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2784 cBar.assertNoCallback();
2785
2786 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2787 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2788 for (TestNetworkCallback c : emptyCallbacks) {
2789 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2790 mWiFiNetworkAgent);
2791 }
2792 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2793 mWiFiNetworkAgent);
2794 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
2795 mWiFiNetworkAgent);
2796 assertNull(
2797 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2798 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002799 cBar.assertNoCallback();
2800
2801 mWiFiNetworkAgent.setNetworkSpecifier(null);
Etan Cohen836ad572018-12-30 17:59:59 -08002802 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002803 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2804 for (TestNetworkCallback c: emptyCallbacks) {
2805 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
2806 }
2807
Etan Cohen836ad572018-12-30 17:59:59 -08002808 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002809 }
2810
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002811 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002812 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002813 try {
2814 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002815 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
2816 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
2817 } catch (IllegalArgumentException expected) {
2818 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002819 }
2820
Etan Cohenddb9ef02015-11-18 10:56:15 -08002821 try {
2822 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2823 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002824 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002825 mService.requestNetwork(networkCapabilities, null, 0, null,
2826 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07002827 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
2828 } catch (IllegalArgumentException expected) {
2829 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08002830 }
2831
Etan Cohena7434272017-04-03 12:17:51 -07002832 class NonParcelableSpecifier extends NetworkSpecifier {
2833 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2834 };
2835 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2836 @Override public int describeContents() { return 0; }
2837 @Override public void writeToParcel(Parcel p, int flags) {}
2838 }
2839 NetworkRequest.Builder builder;
2840
2841 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2842 try {
2843 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2844 Parcel parcelW = Parcel.obtain();
2845 builder.build().writeToParcel(parcelW, 0);
2846 fail("Parceling a non-parcelable specifier did not throw an exception");
2847 } catch (Exception e) {
2848 // expected
2849 }
2850
2851 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2852 builder.setNetworkSpecifier(new ParcelableSpecifier());
2853 NetworkRequest nr = builder.build();
2854 assertNotNull(nr);
2855
2856 try {
2857 Parcel parcelW = Parcel.obtain();
2858 nr.writeToParcel(parcelW, 0);
2859 byte[] bytes = parcelW.marshall();
2860 parcelW.recycle();
2861
2862 Parcel parcelR = Parcel.obtain();
2863 parcelR.unmarshall(bytes, 0, bytes.length);
2864 parcelR.setDataPosition(0);
2865 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
2866 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
2867 } catch (Exception e) {
2868 // expected
2869 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08002870 }
2871
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002872 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07002873 public void testNetworkSpecifierUidSpoofSecurityException() {
2874 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2875 @Override
2876 public boolean satisfiedBy(NetworkSpecifier other) {
2877 return true;
2878 }
2879
2880 @Override
2881 public void assertValidFromUid(int requestorUid) {
2882 throw new SecurityException("failure");
2883 }
2884
2885 @Override
2886 public int describeContents() { return 0; }
2887 @Override
2888 public void writeToParcel(Parcel dest, int flags) {}
2889 }
2890
2891 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2892 mWiFiNetworkAgent.connect(false);
2893
2894 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2895 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2896 networkSpecifier).build();
2897 TestNetworkCallback networkCallback = new TestNetworkCallback();
2898 try {
2899 mCm.requestNetwork(networkRequest, networkCallback);
2900 fail("Network request with spoofed UID did not throw a SecurityException");
2901 } catch (SecurityException e) {
2902 // expected
2903 }
2904 }
2905
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002906 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002907 public void testRegisterDefaultNetworkCallback() throws Exception {
2908 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2909 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2910 defaultNetworkCallback.assertNoCallback();
2911
2912 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2913 // whenever Wi-Fi is up. Without this, the mobile network agent is
2914 // reaped before any other activity can take place.
2915 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2916 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2917 .addTransportType(TRANSPORT_CELLULAR).build();
2918 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2919 cellNetworkCallback.assertNoCallback();
2920
2921 // Bring up cell and expect CALLBACK_AVAILABLE.
2922 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2923 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002924 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2925 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002926 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002927
2928 // Bring up wifi and expect CALLBACK_AVAILABLE.
2929 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2930 mWiFiNetworkAgent.connect(true);
2931 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002932 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002933 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002934
2935 // Bring down cell. Expect no default network callback, since it wasn't the default.
2936 mCellNetworkAgent.disconnect();
2937 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2938 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002939 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002940
2941 // Bring up cell. Expect no default network callback, since it won't be the default.
2942 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2943 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002944 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002945 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002946 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002947
2948 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2949 // followed by AVAILABLE cell.
2950 mWiFiNetworkAgent.disconnect();
2951 cellNetworkCallback.assertNoCallback();
2952 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002953 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002954 mCellNetworkAgent.disconnect();
2955 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2956 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002957 waitForIdle();
2958 assertEquals(null, mCm.getActiveNetwork());
2959
2960 final int uid = Process.myUid();
2961 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
2962 final ArraySet<UidRange> ranges = new ArraySet<>();
2963 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002964 mMockVpn.setNetworkAgent(vpnNetworkAgent);
2965 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002966 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002967 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002968 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2969 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2970
2971 vpnNetworkAgent.disconnect();
2972 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
2973 waitForIdle();
2974 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002975 }
2976
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002977 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09002978 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09002979 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09002980 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09002981 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2982 .addTransportType(TRANSPORT_CELLULAR).build();
2983 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2984
2985 // Bring up the mobile network.
2986 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2987 mCellNetworkAgent.connect(true);
2988
Erik Kline1d3db322017-02-28 16:20:20 +09002989 // We should get onAvailable(), onCapabilitiesChanged(), and
2990 // onLinkPropertiesChanged() in rapid succession. Additionally, we
2991 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002992 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09002993 cellNetworkCallback.assertNoCallback();
2994
2995 // Update LinkProperties.
2996 final LinkProperties lp = new LinkProperties();
2997 lp.setInterfaceName("foonet_data0");
2998 mCellNetworkAgent.sendLinkProperties(lp);
2999 // We should get onLinkPropertiesChanged().
3000 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
3001 cellNetworkCallback.assertNoCallback();
3002
Erik Kline1d3db322017-02-28 16:20:20 +09003003 // Suspend the network.
3004 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003005 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3006 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003007 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
3008 cellNetworkCallback.assertNoCallback();
3009
Erik Klineacdd6392016-07-07 16:50:58 +09003010 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003011 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003012 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003013 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3014 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003015 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003016 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003017 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3018
3019 mCellNetworkAgent.resume();
3020 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3021 mCellNetworkAgent);
3022 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
3023 cellNetworkCallback.assertNoCallback();
3024
3025 dfltNetworkCallback = new TestNetworkCallback();
3026 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3027 // This time onNetworkSuspended should not be called.
3028 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3029 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003030
Erik Klineacdd6392016-07-07 16:50:58 +09003031 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3032 mCm.unregisterNetworkCallback(cellNetworkCallback);
3033 }
3034
Calvin On1f64f3f2016-10-11 15:10:46 -07003035 private void setCaptivePortalMode(int mode) {
3036 ContentResolver cr = mServiceContext.getContentResolver();
3037 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3038 }
3039
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003040 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003041 ContentResolver cr = mServiceContext.getContentResolver();
3042 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003043 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003044 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003045 }
3046
Erik Kline79c6d052018-03-21 07:18:33 -07003047 private void setPrivateDnsSettings(String mode, String specifier) {
3048 final ContentResolver cr = mServiceContext.getContentResolver();
3049 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3050 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3051 mService.updatePrivateDnsSettings();
3052 waitForIdle();
3053 }
3054
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003055 private boolean isForegroundNetwork(MockNetworkAgent network) {
3056 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3057 assertNotNull(nc);
3058 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3059 }
3060
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003061 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003062 public void testBackgroundNetworks() throws Exception {
3063 // Create a background request. We can't do this ourselves because ConnectivityService
3064 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003065 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003066 final NetworkRequest request = new NetworkRequest.Builder().build();
3067 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3068 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3069 final TestNetworkCallback callback = new TestNetworkCallback();
3070 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3071 mCm.registerNetworkCallback(request, callback);
3072 mCm.registerNetworkCallback(fgRequest, fgCallback);
3073
3074 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3075 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003076 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3077 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003078 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3079
3080 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3081 mWiFiNetworkAgent.connect(true);
3082
3083 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003084 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003085 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003086 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003087 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003088 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003089 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003090 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3091 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3092
3093 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003094 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003095 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3096 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003097 // Expect a network capabilities update sans FOREGROUND.
3098 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003099 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3100 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3101
3102 // File a cell request and check that cell comes into the foreground.
3103 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3104 .addTransportType(TRANSPORT_CELLULAR).build();
3105 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3106 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003107 // NOTE: This request causes the network's capabilities to change. This
3108 // is currently delivered before the onAvailable() callbacks.
3109 // TODO: Fix this.
3110 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003111 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3112 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003113 // Expect a network capabilities update with FOREGROUND, because the most recent
3114 // request causes its state to change.
3115 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003116 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3117 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3118
3119 // Release the request. The network immediately goes into the background, since it was not
3120 // lingering.
3121 mCm.unregisterNetworkCallback(cellCallback);
3122 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003123 // Expect a network capabilities update sans FOREGROUND.
3124 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003125 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3126 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3127
3128 // Disconnect wifi and check that cell is foreground again.
3129 mWiFiNetworkAgent.disconnect();
3130 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3131 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003132 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003133 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3134
3135 mCm.unregisterNetworkCallback(callback);
3136 mCm.unregisterNetworkCallback(fgCallback);
3137 }
3138
Hugo Benichi849b81b2017-05-25 13:42:31 +09003139 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003140 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003141 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003142 // Benchmarks connecting and switching performance in the presence of a large number of
3143 // NetworkRequests.
3144 // 1. File NUM_REQUESTS requests.
3145 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3146 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3147 // and NUM_REQUESTS onAvailable callbacks to fire.
3148 // See how long it took.
3149 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003150 final int REGISTER_TIME_LIMIT_MS = 200;
3151 final int CONNECT_TIME_LIMIT_MS = 60;
3152 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003153 final int UNREGISTER_TIME_LIMIT_MS = 20;
3154
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003155 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3156 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3157 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3158 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3159
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003160 for (int i = 0; i < NUM_REQUESTS; i++) {
3161 callbacks[i] = new NetworkCallback() {
3162 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3163 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3164 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003165 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003166
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003167 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3168 for (NetworkCallback cb : callbacks) {
3169 mCm.registerNetworkCallback(request, cb);
3170 }
3171 });
3172
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003173 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3174 // Don't request that the network validate, because otherwise connect() will block until
3175 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3176 // and we won't actually measure anything.
3177 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003178
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003179 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003180 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003181 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003182 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3183 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3184 onAvailableDispatchingDuration));
3185 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3186 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3187 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003188
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003189 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003190 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003191 mWiFiNetworkAgent.adjustScore(40);
3192 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003193
3194 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003195 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003196 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003197 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3198 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3199 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3200 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3201 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003202
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003203 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3204 for (NetworkCallback cb : callbacks) {
3205 mCm.unregisterNetworkCallback(cb);
3206 }
3207 });
3208 }
3209
3210 private long durationOf(Runnable fn) {
3211 long startTime = SystemClock.elapsedRealtime();
3212 fn.run();
3213 return SystemClock.elapsedRealtime() - startTime;
3214 }
3215
3216 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3217 long timeTaken = durationOf(fn);
3218 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003219 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003220 assertTrue(msg, timeTaken <= timeLimit);
3221 }
3222
3223 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3224 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09003225 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003226 } catch (InterruptedException e) {}
3227 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003228 }
3229
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003230 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003231 public void testMobileDataAlwaysOn() throws Exception {
3232 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3233 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3234 .addTransportType(TRANSPORT_CELLULAR).build();
3235 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3236
3237 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3238 handlerThread.start();
3239 NetworkCapabilities filter = new NetworkCapabilities()
3240 .addTransportType(TRANSPORT_CELLULAR)
3241 .addCapability(NET_CAPABILITY_INTERNET);
3242 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3243 mServiceContext, "testFactory", filter);
3244 testFactory.setScoreFilter(40);
3245
3246 // Register the factory and expect it to start looking for a network.
Chalard Jean08577fc2018-05-02 21:14:54 +09003247 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003248 testFactory.register();
3249 testFactory.waitForNetworkRequests(1);
3250 assertTrue(testFactory.getMyStartRequested());
3251
3252 // Bring up wifi. The factory stops looking for a network.
3253 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Chalard Jean08577fc2018-05-02 21:14:54 +09003254 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3255 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003256 mWiFiNetworkAgent.connect(true);
Chalard Jean08577fc2018-05-02 21:14:54 +09003257 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003258 assertFalse(testFactory.getMyStartRequested());
3259
3260 ContentResolver cr = mServiceContext.getContentResolver();
3261
3262 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean08577fc2018-05-02 21:14:54 +09003263 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003264 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003265 testFactory.waitForNetworkRequests(2);
3266 assertTrue(testFactory.getMyStartRequested());
3267
3268 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003269 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003270 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Chalard Jean08577fc2018-05-02 21:14:54 +09003271 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003272 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003273 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003274 testFactory.waitForNetworkRequests(2);
3275 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3276
3277 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003278 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003279 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003280 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003281
3282 // Turn off mobile data always on and expect the request to disappear...
3283 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003284 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003285 testFactory.waitForNetworkRequests(1);
3286
3287 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003288 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003289 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003290
3291 testFactory.unregister();
3292 mCm.unregisterNetworkCallback(cellNetworkCallback);
3293 handlerThread.quit();
3294 }
3295
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003296 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003297 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003298 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003299 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003300 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3301
Erik Kline065ab6e2016-10-02 18:02:14 +09003302 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003303 String[] values = new String[] {null, "0", "1"};
3304 for (int i = 0; i < values.length; i++) {
3305 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003306 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003307 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003308 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003309 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003310 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003311 }
3312
Erik Kline065ab6e2016-10-02 18:02:14 +09003313 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003314
3315 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003316 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003317 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003318 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003319 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003320
3321 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003322 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003323 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003324 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003325 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003326
3327 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003328 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003329 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003330 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003331 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003332 }
3333
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003334 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003335 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003336 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003337 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003338
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003339 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003340 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003341
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003342 // File a request for cell to ensure it doesn't go down.
3343 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3344 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3345 .addTransportType(TRANSPORT_CELLULAR).build();
3346 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3347
3348 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3349 mCm.registerDefaultNetworkCallback(defaultCallback);
3350
3351 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3352 .addTransportType(TRANSPORT_WIFI)
3353 .addCapability(NET_CAPABILITY_VALIDATED)
3354 .build();
3355 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3356 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3357
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003358 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003359 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003360
3361 // Bring up validated cell.
3362 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3363 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003364 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3365 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003366 Network cellNetwork = mCellNetworkAgent.getNetwork();
3367
3368 // Bring up validated wifi.
3369 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3370 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003371 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3372 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003373 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3374
3375 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003376 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003377 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003378 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003379 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3380
3381 // Because avoid bad wifi is off, we don't switch to cellular.
3382 defaultCallback.assertNoCallback();
3383 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3384 NET_CAPABILITY_VALIDATED));
3385 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3386 NET_CAPABILITY_VALIDATED));
3387 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3388
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003389 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3390 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003391 tracker.configRestrictsAvoidBadWifi = false;
3392 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003393 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003394 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3395
3396 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003397 tracker.configRestrictsAvoidBadWifi = true;
3398 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003399 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003400 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3401
3402 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3403 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003404 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003405 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3406 NET_CAPABILITY_VALIDATED));
3407 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3408 NET_CAPABILITY_VALIDATED));
3409 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3410
3411 // Disconnect and reconnect wifi to clear the one-time switch above.
3412 mWiFiNetworkAgent.disconnect();
3413 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3414 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003415 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3416 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003417 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3418
3419 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003420 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003421 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003422 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003423 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3424
3425 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003426 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003427 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003428
3429 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003430 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003431 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3432 NET_CAPABILITY_VALIDATED));
3433 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3434 NET_CAPABILITY_VALIDATED));
3435 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3436
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003437 // Simulate the user turning the cellular fallback setting off and then on.
3438 // We switch to wifi and then to cell.
3439 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003440 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003441 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003442 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3443 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003444 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003445 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003446 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3447
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003448 // If cell goes down, we switch to wifi.
3449 mCellNetworkAgent.disconnect();
3450 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003451 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003452 validatedWifiCallback.assertNoCallback();
3453
3454 mCm.unregisterNetworkCallback(cellNetworkCallback);
3455 mCm.unregisterNetworkCallback(validatedWifiCallback);
3456 mCm.unregisterNetworkCallback(defaultCallback);
3457 }
3458
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003459 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003460 public void testMeteredMultipathPreferenceSetting() throws Exception {
3461 final ContentResolver cr = mServiceContext.getContentResolver();
3462 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3463 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3464
3465 for (int config : Arrays.asList(0, 3, 2)) {
3466 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3467 tracker.configMeteredMultipathPreference = config;
3468 Settings.Global.putString(cr, settingName, setting);
3469 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003470 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003471
3472 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3473 String msg = String.format("config=%d, setting=%s", config, setting);
3474 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3475 }
3476 }
3477 }
3478
Erik Kline3841a482015-11-25 12:49:38 +09003479 /**
3480 * Validate that a satisfied network request does not trigger onUnavailable() once the
3481 * time-out period expires.
3482 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003483 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003484 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3485 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3486 NetworkCapabilities.TRANSPORT_WIFI).build();
3487 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003488 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003489
3490 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3491 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003492 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003493 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003494
3495 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003496 networkCallback.assertNoCallback();
3497 }
3498
3499 /**
3500 * Validate that a satisfied network request followed by a disconnected (lost) network does
3501 * not trigger onUnavailable() once the time-out period expires.
3502 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003503 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003504 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3505 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3506 NetworkCapabilities.TRANSPORT_WIFI).build();
3507 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003508 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003509
3510 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3511 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003512 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003513 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003514 mWiFiNetworkAgent.disconnect();
3515 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3516
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003517 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003518 networkCallback.assertNoCallback();
3519 }
3520
3521 /**
3522 * Validate that when a time-out is specified for a network request the onUnavailable()
3523 * callback is called when time-out expires. Then validate that if network request is
3524 * (somehow) satisfied - the callback isn't called later.
3525 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003526 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003527 public void testTimedoutNetworkRequest() {
3528 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3529 NetworkCapabilities.TRANSPORT_WIFI).build();
3530 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003531 final int timeoutMs = 10;
3532 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003533
3534 // pass timeout and validate that UNAVAILABLE is called
3535 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3536
3537 // create a network satisfying request - validate that request not triggered
3538 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3539 mWiFiNetworkAgent.connect(false);
3540 networkCallback.assertNoCallback();
3541 }
3542
3543 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003544 * Validate that when a network request is unregistered (cancelled), no posterior event can
3545 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003546 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003547 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003548 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003549 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3550 NetworkCapabilities.TRANSPORT_WIFI).build();
3551 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003552 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003553
Hugo Benichidfb559a2016-12-20 14:57:49 +09003554 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003555 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003556 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3557 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003558 networkCallback.assertNoCallback();
3559
3560 // create a network satisfying request - validate that request not triggered
3561 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3562 mWiFiNetworkAgent.connect(false);
3563 networkCallback.assertNoCallback();
3564 }
3565
Etan Cohenae574a82019-01-08 12:09:18 -08003566 /**
3567 * Validate the callback flow for a factory releasing a request as unfulfillable.
3568 */
3569 @Test
3570 public void testUnfulfillableNetworkRequest() throws Exception {
3571 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3572 NetworkCapabilities.TRANSPORT_WIFI).build();
3573 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3574
3575 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3576 handlerThread.start();
3577 NetworkCapabilities filter = new NetworkCapabilities()
3578 .addTransportType(TRANSPORT_WIFI)
3579 .addCapability(NET_CAPABILITY_INTERNET);
3580 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3581 mServiceContext, "testFactory", filter);
3582 testFactory.setScoreFilter(40);
3583
3584 // Register the factory and expect it to receive the default request.
3585 testFactory.expectAddRequestsWithScores(0);
3586 testFactory.register();
3587 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3588
3589 assertEquals(1, requests.size()); // have 1 request at this point
3590 int origRequestId = requests.valueAt(0).requestId;
3591
3592 // Now file the test request and expect it.
3593 testFactory.expectAddRequestsWithScores(0);
3594 mCm.requestNetwork(nr, networkCallback);
3595 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3596
3597 int newRequestId = 0;
3598 for (int i = 0; i < requests.size(); ++i) {
3599 if (requests.valueAt(i).requestId != origRequestId) {
3600 newRequestId = requests.valueAt(i).requestId;
3601 break;
3602 }
3603 }
3604
3605 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
3606 testFactory.expectRemoveRequests(1);
3607 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3608 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3609 testFactory.waitForRequests();
3610
3611 testFactory.unregister();
3612 handlerThread.quit();
3613 }
3614
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003615 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3616
3617 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3618
3619 private class CallbackValue {
3620 public CallbackType callbackType;
3621 public int error;
3622
3623 public CallbackValue(CallbackType type) {
3624 this.callbackType = type;
3625 this.error = PacketKeepalive.SUCCESS;
3626 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3627 }
3628
3629 public CallbackValue(CallbackType type, int error) {
3630 this.callbackType = type;
3631 this.error = error;
3632 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3633 }
3634
3635 @Override
3636 public boolean equals(Object o) {
3637 return o instanceof CallbackValue &&
3638 this.callbackType == ((CallbackValue) o).callbackType &&
3639 this.error == ((CallbackValue) o).error;
3640 }
3641
3642 @Override
3643 public String toString() {
3644 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3645 }
3646 }
3647
3648 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3649
3650 @Override
3651 public void onStarted() {
3652 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3653 }
3654
3655 @Override
3656 public void onStopped() {
3657 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3658 }
3659
3660 @Override
3661 public void onError(int error) {
3662 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3663 }
3664
3665 private void expectCallback(CallbackValue callbackValue) {
3666 try {
3667 assertEquals(
3668 callbackValue,
3669 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3670 } catch (InterruptedException e) {
3671 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3672 }
3673 }
3674
3675 public void expectStarted() {
3676 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3677 }
3678
3679 public void expectStopped() {
3680 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3681 }
3682
3683 public void expectError(int error) {
3684 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3685 }
3686 }
3687
junyulai48eac1d42018-12-27 17:25:29 +08003688 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3689
3690 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3691
3692 private class CallbackValue {
3693 public CallbackType callbackType;
3694 public int error;
3695
3696 CallbackValue(CallbackType type) {
3697 this.callbackType = type;
3698 this.error = SocketKeepalive.SUCCESS;
3699 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3700 }
3701
3702 CallbackValue(CallbackType type, int error) {
3703 this.callbackType = type;
3704 this.error = error;
3705 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3706 }
3707
3708 @Override
3709 public boolean equals(Object o) {
3710 return o instanceof CallbackValue
3711 && this.callbackType == ((CallbackValue) o).callbackType
3712 && this.error == ((CallbackValue) o).error;
3713 }
3714
3715 @Override
3716 public String toString() {
3717 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3718 error);
3719 }
3720 }
3721
3722 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
3723
3724 @Override
3725 public void onStarted() {
3726 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3727 }
3728
3729 @Override
3730 public void onStopped() {
3731 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3732 }
3733
3734 @Override
3735 public void onError(int error) {
3736 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3737 }
3738
3739 private void expectCallback(CallbackValue callbackValue) {
3740 try {
3741 assertEquals(
3742 callbackValue,
3743 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3744 } catch (InterruptedException e) {
3745 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
3746 }
3747 }
3748
3749 public void expectStarted() {
3750 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3751 }
3752
3753 public void expectStopped() {
3754 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3755 }
3756
3757 public void expectError(int error) {
3758 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3759 }
3760 }
3761
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003762 private Network connectKeepaliveNetwork(LinkProperties lp) {
3763 // Ensure the network is disconnected before we do anything.
3764 if (mWiFiNetworkAgent != null) {
3765 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3766 }
3767
3768 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3769 ConditionVariable cv = waitForConnectivityBroadcasts(1);
3770 mWiFiNetworkAgent.connect(true);
3771 waitFor(cv);
3772 verifyActiveNetwork(TRANSPORT_WIFI);
3773 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003774 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003775 return mWiFiNetworkAgent.getNetwork();
3776 }
3777
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003778 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003779 public void testPacketKeepalives() throws Exception {
3780 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3781 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3782 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3783 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3784 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3785
Nathan Harold63dd8132018-02-14 13:09:45 -08003786 final int validKaInterval = 15;
3787 final int invalidKaInterval = 9;
3788
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003789 LinkProperties lp = new LinkProperties();
3790 lp.setInterfaceName("wlan12");
3791 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3792 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3793 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3794 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3795
3796 Network notMyNet = new Network(61234);
3797 Network myNet = connectKeepaliveNetwork(lp);
3798
3799 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3800 PacketKeepalive ka;
3801
3802 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003803 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003804 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3805
Nathan Harold63dd8132018-02-14 13:09:45 -08003806 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003807 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3808
Nathan Harold63dd8132018-02-14 13:09:45 -08003809 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003810 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3811
Nathan Harold63dd8132018-02-14 13:09:45 -08003812 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003813 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3814
Nathan Harold63dd8132018-02-14 13:09:45 -08003815 // NAT-T is only supported for IPv4.
3816 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3817 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003818
Nathan Harold63dd8132018-02-14 13:09:45 -08003819 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003820 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3821
Nathan Harold63dd8132018-02-14 13:09:45 -08003822 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003823 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3824
Nathan Harold63dd8132018-02-14 13:09:45 -08003825 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003826 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3827
Nathan Harold63dd8132018-02-14 13:09:45 -08003828 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003829 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3830
3831 // Check that a started keepalive can be stopped.
3832 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003833 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003834 callback.expectStarted();
3835 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
3836 ka.stop();
3837 callback.expectStopped();
3838
3839 // Check that deleting the IP address stops the keepalive.
3840 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003841 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003842 callback.expectStarted();
3843 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3844 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3845 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3846 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3847 mWiFiNetworkAgent.sendLinkProperties(lp);
3848
3849 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003850 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003851 callback.expectStarted();
3852 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003853 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003854 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3855
3856 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003857 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003858 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003859 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003860 ka.stop();
3861
3862 // Reconnect.
3863 myNet = connectKeepaliveNetwork(lp);
3864 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3865
3866 // Check things work as expected when the keepalive is stopped and the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003867 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003868 callback.expectStarted();
3869 ka.stop();
3870 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003871 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09003872 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003873 callback.expectStopped();
3874
3875 // Reconnect.
3876 myNet = connectKeepaliveNetwork(lp);
3877 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
3878
3879 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3880 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003881 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003882 callback.expectStarted();
3883
3884 // The second one gets slot 2.
3885 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3886 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003887 PacketKeepalive ka2 = mCm.startNattKeepalive(
3888 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003889 callback2.expectStarted();
3890
3891 // Now stop the first one and create a third. This also gets slot 1.
3892 ka.stop();
3893 callback.expectStopped();
3894
3895 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3896 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003897 PacketKeepalive ka3 = mCm.startNattKeepalive(
3898 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003899 callback3.expectStarted();
3900
3901 ka2.stop();
3902 callback2.expectStopped();
3903
3904 ka3.stop();
3905 callback3.expectStopped();
3906 }
Udam Sainib7c24872016-01-04 12:16:14 -08003907
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003908 @Test
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003909 public void testNattSocketKeepalives_SingleThreadExecutor() throws Exception {
junyulaie4135282019-01-03 18:50:15 +08003910 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
3911 doTestNattSocketKeepalivesWithExecutor(executorSingleThread);
3912 executorSingleThread.shutdown();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003913 }
junyulaie4135282019-01-03 18:50:15 +08003914
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003915 @Test
3916 public void testNattSocketKeepalives_InlineExecutor() throws Exception {
junyulaie4135282019-01-03 18:50:15 +08003917 final Executor executorInline = (Runnable r) -> r.run();
3918 doTestNattSocketKeepalivesWithExecutor(executorInline);
3919 }
3920
3921 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08003922 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulaie4135282019-01-03 18:50:15 +08003923 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai48eac1d42018-12-27 17:25:29 +08003924 final int srcPort = 12345;
3925 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3926 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3927 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3928 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3929 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3930
3931 final int validKaInterval = 15;
3932 final int invalidKaInterval = 9;
3933
3934 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
3935 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort);
3936
junyulai48eac1d42018-12-27 17:25:29 +08003937 LinkProperties lp = new LinkProperties();
3938 lp.setInterfaceName("wlan12");
3939 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3940 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3941 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3942 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3943
3944 Network notMyNet = new Network(61234);
3945 Network myNet = connectKeepaliveNetwork(lp);
3946
3947 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
3948 SocketKeepalive ka;
3949
3950 // Attempt to start keepalives with invalid parameters and check for errors.
3951 // Invalid network.
3952 ka = mCm.createSocketKeepalive(notMyNet, testSocket, myIPv4, dstIPv4, executor, callback);
3953 ka.start(validKaInterval);
3954 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3955
3956 // Invalid interval.
3957 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3958 ka.start(invalidKaInterval);
3959 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
3960
3961 // Invalid destination.
3962 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv6, executor, callback);
3963 ka.start(validKaInterval);
3964 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3965
3966 // Invalid source;
3967 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv4, executor, callback);
3968 ka.start(validKaInterval);
3969 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3970
3971 // NAT-T is only supported for IPv4.
3972 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv6, executor, callback);
3973 ka.start(validKaInterval);
3974 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3975
3976 // Sanity check before testing started keepalive.
3977 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3978 ka.start(validKaInterval);
3979 callback.expectError(SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3980
3981 // Check that a started keepalive can be stopped.
3982 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
3983 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3984 ka.start(validKaInterval);
3985 callback.expectStarted();
3986 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
3987 ka.stop();
3988 callback.expectStopped();
3989
3990 // Check that deleting the IP address stops the keepalive.
3991 LinkProperties bogusLp = new LinkProperties(lp);
3992 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
3993 ka.start(validKaInterval);
3994 callback.expectStarted();
3995 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3996 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3997 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3998 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3999 mWiFiNetworkAgent.sendLinkProperties(lp);
4000
4001 // Check that a started keepalive is stopped correctly when the network disconnects.
4002 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
4003 ka.start(validKaInterval);
4004 callback.expectStarted();
4005 mWiFiNetworkAgent.disconnect();
4006 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4007 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4008
4009 // ... and that stopping it after that has no adverse effects.
4010 waitForIdle();
4011 final Network myNetAlias = myNet;
4012 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4013 ka.stop();
4014
4015 // Reconnect.
4016 myNet = connectKeepaliveNetwork(lp);
4017 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4018
4019 // Check things work as expected when the keepalive is stopped and the network disconnects.
4020 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
4021 ka.start(validKaInterval);
4022 callback.expectStarted();
4023 ka.stop();
4024 mWiFiNetworkAgent.disconnect();
4025 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4026 waitForIdle();
4027 callback.expectStopped();
4028
4029 // Reconnect.
4030 myNet = connectKeepaliveNetwork(lp);
4031 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4032
4033 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4034 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4035 ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
4036 ka.start(validKaInterval);
4037 callback.expectStarted();
4038
4039 // The second one gets slot 2.
4040 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4041 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
4042 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback();
4043 SocketKeepalive ka2 =
4044 mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2);
4045 ka2.start(validKaInterval);
4046 callback2.expectStarted();
4047
4048 ka.stop();
4049 callback.expectStopped();
4050
4051 ka2.stop();
4052 callback2.expectStopped();
junyulaie4135282019-01-03 18:50:15 +08004053
4054 testSocket.close();
4055 testSocket2.close();
4056
4057 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004058 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
junyulai48eac1d42018-12-27 17:25:29 +08004059 }
4060
4061 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004062 public void testGetCaptivePortalServerUrl() throws Exception {
4063 String url = mCm.getCaptivePortalServerUrl();
4064 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4065 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004066
4067 private static class TestNetworkPinner extends NetworkPinner {
4068 public static boolean awaitPin(int timeoutMs) {
4069 synchronized(sLock) {
4070 if (sNetwork == null) {
4071 try {
4072 sLock.wait(timeoutMs);
4073 } catch (InterruptedException e) {}
4074 }
4075 return sNetwork != null;
4076 }
4077 }
4078
4079 public static boolean awaitUnpin(int timeoutMs) {
4080 synchronized(sLock) {
4081 if (sNetwork != null) {
4082 try {
4083 sLock.wait(timeoutMs);
4084 } catch (InterruptedException e) {}
4085 }
4086 return sNetwork == null;
4087 }
4088 }
4089 }
4090
4091 private void assertPinnedToWifiWithCellDefault() {
4092 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4093 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4094 }
4095
4096 private void assertPinnedToWifiWithWifiDefault() {
4097 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4098 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4099 }
4100
4101 private void assertNotPinnedToWifi() {
4102 assertNull(mCm.getBoundNetworkForProcess());
4103 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4104 }
4105
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004106 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004107 public void testNetworkPinner() {
4108 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4109 .addTransportType(TRANSPORT_WIFI)
4110 .build();
4111 assertNull(mCm.getBoundNetworkForProcess());
4112
4113 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4114 assertNull(mCm.getBoundNetworkForProcess());
4115
4116 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4117 mCellNetworkAgent.connect(true);
4118 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4119 mWiFiNetworkAgent.connect(false);
4120
4121 // When wi-fi connects, expect to be pinned.
4122 assertTrue(TestNetworkPinner.awaitPin(100));
4123 assertPinnedToWifiWithCellDefault();
4124
4125 // Disconnect and expect the pin to drop.
4126 mWiFiNetworkAgent.disconnect();
4127 assertTrue(TestNetworkPinner.awaitUnpin(100));
4128 assertNotPinnedToWifi();
4129
4130 // Reconnecting does not cause the pin to come back.
4131 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4132 mWiFiNetworkAgent.connect(false);
4133 assertFalse(TestNetworkPinner.awaitPin(100));
4134 assertNotPinnedToWifi();
4135
4136 // Pinning while connected causes the pin to take effect immediately.
4137 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4138 assertTrue(TestNetworkPinner.awaitPin(100));
4139 assertPinnedToWifiWithCellDefault();
4140
4141 // Explicitly unpin and expect to use the default network again.
4142 TestNetworkPinner.unpin();
4143 assertNotPinnedToWifi();
4144
4145 // Disconnect cell and wifi.
4146 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4147 mCellNetworkAgent.disconnect();
4148 mWiFiNetworkAgent.disconnect();
4149 waitFor(cv);
4150
4151 // Pinning takes effect even if the pinned network is the default when the pin is set...
4152 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4153 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4154 mWiFiNetworkAgent.connect(false);
4155 assertTrue(TestNetworkPinner.awaitPin(100));
4156 assertPinnedToWifiWithWifiDefault();
4157
4158 // ... and is maintained even when that network is no longer the default.
4159 cv = waitForConnectivityBroadcasts(1);
4160 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4161 mCellNetworkAgent.connect(true);
4162 waitFor(cv);
4163 assertPinnedToWifiWithCellDefault();
4164 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004165
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004166 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004167 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004168 // We can only have 99 callbacks, because MultipathPolicyTracker is
4169 // already one of them.
4170 final int MAX_REQUESTS = 99;
4171 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004172 final int INTENTS = 10;
4173 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4174
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004175 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004176 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004177
Hugo Benichi893a7622017-09-29 09:34:08 +09004178 int j = 0;
4179 while (j++ < CALLBACKS / 2) {
4180 NetworkCallback cb = new NetworkCallback();
4181 mCm.requestNetwork(networkRequest, cb);
4182 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004183 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004184 while (j++ < CALLBACKS) {
4185 NetworkCallback cb = new NetworkCallback();
4186 mCm.registerNetworkCallback(networkRequest, cb);
4187 registered.add(cb);
4188 }
4189 j = 0;
4190 while (j++ < INTENTS / 2) {
4191 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4192 mCm.requestNetwork(networkRequest, pi);
4193 registered.add(pi);
4194 }
4195 while (j++ < INTENTS) {
4196 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4197 mCm.registerNetworkCallback(networkRequest, pi);
4198 registered.add(pi);
4199 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004200
Hugo Benichi893a7622017-09-29 09:34:08 +09004201 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004202 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09004203 mCm.requestNetwork(networkRequest, new NetworkCallback());
4204 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09004205 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09004206 try {
4207 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4208 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4209 } catch (TooManyRequestsException expected) {}
4210 try {
4211 mCm.requestNetwork(networkRequest,
4212 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4213 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4214 } catch (TooManyRequestsException expected) {}
4215 try {
4216 mCm.registerNetworkCallback(networkRequest,
4217 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4218 fail("Registering " + MAX_REQUESTS
4219 + " PendingIntent callbacks did not throw exception");
4220 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004221
Hugo Benichi893a7622017-09-29 09:34:08 +09004222 for (Object o : registered) {
4223 if (o instanceof NetworkCallback) {
4224 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004225 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004226 if (o instanceof PendingIntent) {
4227 mCm.unregisterNetworkCallback((PendingIntent)o);
4228 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004229 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004230 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004231
4232 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4233 for (int i = 0; i < MAX_REQUESTS; i++) {
4234 NetworkCallback networkCallback = new NetworkCallback();
4235 mCm.requestNetwork(networkRequest, networkCallback);
4236 mCm.unregisterNetworkCallback(networkCallback);
4237 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004238 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004239
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004240 for (int i = 0; i < MAX_REQUESTS; i++) {
4241 NetworkCallback networkCallback = new NetworkCallback();
4242 mCm.registerNetworkCallback(networkRequest, networkCallback);
4243 mCm.unregisterNetworkCallback(networkCallback);
4244 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004245 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004246
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004247 for (int i = 0; i < MAX_REQUESTS; i++) {
4248 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004249 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004250 mCm.requestNetwork(networkRequest, pendingIntent);
4251 mCm.unregisterNetworkCallback(pendingIntent);
4252 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004253 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004254
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004255 for (int i = 0; i < MAX_REQUESTS; i++) {
4256 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004257 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004258 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4259 mCm.unregisterNetworkCallback(pendingIntent);
4260 }
4261 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004262
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004263 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004264 public void testNetworkInfoOfTypeNone() {
4265 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4266
4267 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09004268 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004269 assertNull(mCm.getActiveNetworkInfo());
4270
4271 Network[] allNetworks = mCm.getAllNetworks();
4272 assertLength(1, allNetworks);
4273 Network network = allNetworks[0];
4274 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4275 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4276
4277 final NetworkRequest request =
4278 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4279 final TestNetworkCallback callback = new TestNetworkCallback();
4280 mCm.registerNetworkCallback(request, callback);
4281
Hugo Benichic1014502017-07-19 10:10:52 +09004282 // Bring up wifi aware network.
4283 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004284 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004285
4286 assertNull(mCm.getActiveNetworkInfo());
4287 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004288 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004289 // of this test. Fix it and uncomment the assert below.
4290 //assertEmpty(mCm.getAllNetworkInfo());
4291
Hugo Benichic1014502017-07-19 10:10:52 +09004292 // Disconnect wifi aware network.
4293 wifiAware.disconnect();
4294 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004295 mCm.unregisterNetworkCallback(callback);
4296
4297 verifyNoNetwork();
4298 if (broadcastCV.block(10)) {
4299 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4300 }
4301 }
4302
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004303 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004304 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4305 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4306 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4307 assertNull(mCm.getNetworkForType(TYPE_NONE));
4308 assertNull(mCm.getLinkProperties(TYPE_NONE));
4309 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4310
4311 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4312 IllegalArgumentException.class);
4313
4314 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4315 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4316 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4317 // TODO: let test context have configuration application target sdk version
4318 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4319 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4320 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4321 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4322 }
4323
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004324 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01004325 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4326 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4327 .addTransportType(TRANSPORT_WIFI).build();
4328 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4329 mCm.registerNetworkCallback(networkRequest, networkCallback);
4330
4331 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004332 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004333 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4334 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4335 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4336 lp.addLinkAddress(myIpv4Address);
4337 lp.addRoute(myIpv4DefaultRoute);
4338
4339 // Verify direct routes are added when network agent is first registered in
4340 // ConnectivityService.
4341 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4342 networkAgent.connect(true);
4343 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4344 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4345 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4346 networkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004347 networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004348 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4349 networkCallback.assertNoCallback();
4350 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4351 Arrays.asList(myIpv4DefaultRoute));
4352 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4353 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4354
4355 // Verify direct routes are added during subsequent link properties updates.
4356 LinkProperties newLp = new LinkProperties(lp);
4357 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4358 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4359 newLp.addLinkAddress(myIpv6Address1);
4360 newLp.addLinkAddress(myIpv6Address2);
4361 networkAgent.sendLinkProperties(newLp);
4362 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4363 networkCallback.assertNoCallback();
4364 checkDirectlyConnectedRoutes(cbi.arg,
4365 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4366 Arrays.asList(myIpv4DefaultRoute));
4367 mCm.unregisterNetworkCallback(networkCallback);
4368 }
4369
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004370 @Test
4371 public void testStatsIfacesChanged() throws Exception {
4372 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004373 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4374
Varun Anand02c50ef2019-02-07 14:13:13 -08004375 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4376 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4377
4378 LinkProperties cellLp = new LinkProperties();
4379 cellLp.setInterfaceName(MOBILE_IFNAME);
4380 LinkProperties wifiLp = new LinkProperties();
4381 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004382
4383 // Simple connection should have updated ifaces
4384 mCellNetworkAgent.connect(false);
Varun Anand02c50ef2019-02-07 14:13:13 -08004385 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004386 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004387 verify(mStatsService, atLeastOnce())
4388 .forceUpdateIfaces(
4389 eq(onlyCell),
4390 eq(new VpnInfo[0]),
4391 any(NetworkState[].class),
4392 eq(MOBILE_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004393 reset(mStatsService);
4394
4395 // Default network switch should update ifaces.
4396 mWiFiNetworkAgent.connect(false);
Varun Anand02c50ef2019-02-07 14:13:13 -08004397 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004398 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004399 assertEquals(wifiLp, mService.getActiveLinkProperties());
4400 verify(mStatsService, atLeastOnce())
4401 .forceUpdateIfaces(
4402 eq(onlyWifi),
4403 eq(new VpnInfo[0]),
4404 any(NetworkState[].class),
4405 eq(WIFI_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004406 reset(mStatsService);
4407
4408 // Disconnect should update ifaces.
4409 mWiFiNetworkAgent.disconnect();
4410 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004411 verify(mStatsService, atLeastOnce())
4412 .forceUpdateIfaces(
4413 eq(onlyCell),
4414 eq(new VpnInfo[0]),
4415 any(NetworkState[].class),
4416 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004417 reset(mStatsService);
4418
4419 // Metered change should update ifaces
4420 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4421 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004422 verify(mStatsService, atLeastOnce())
4423 .forceUpdateIfaces(
4424 eq(onlyCell),
4425 eq(new VpnInfo[0]),
4426 any(NetworkState[].class),
4427 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004428 reset(mStatsService);
4429
4430 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4431 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004432 verify(mStatsService, atLeastOnce())
4433 .forceUpdateIfaces(
4434 eq(onlyCell),
4435 eq(new VpnInfo[0]),
4436 any(NetworkState[].class),
4437 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004438 reset(mStatsService);
4439
4440 // Captive portal change shouldn't update ifaces
4441 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4442 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004443 verify(mStatsService, never())
4444 .forceUpdateIfaces(
4445 eq(onlyCell),
4446 eq(new VpnInfo[0]),
4447 any(NetworkState[].class),
4448 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004449 reset(mStatsService);
4450
4451 // Roaming change should update ifaces
4452 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4453 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004454 verify(mStatsService, atLeastOnce())
4455 .forceUpdateIfaces(
4456 eq(onlyCell),
4457 eq(new VpnInfo[0]),
4458 any(NetworkState[].class),
4459 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004460 reset(mStatsService);
4461 }
4462
Erik Klinee89953b2018-01-11 16:11:10 +09004463 @Test
4464 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004465 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4466 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
4467
4468 // Clear any interactions that occur as a result of CS starting up.
4469 reset(mNetworkManagementService);
4470
4471 final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Klinee89953b2018-01-11 16:11:10 +09004472 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4473 waitForIdle();
4474 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
Erik Kline79c6d052018-03-21 07:18:33 -07004475 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
4476 verifyNoMoreInteractions(mNetworkManagementService);
Erik Klinee89953b2018-01-11 16:11:10 +09004477
4478 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004479 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004480 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4481 // "is-reachable" testing in order to not program netd with unreachable
4482 // nameservers that it might try repeated to validate.
4483 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004484 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4485 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004486 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004487 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4488 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004489 mCellNetworkAgent.sendLinkProperties(cellLp);
4490 mCellNetworkAgent.connect(false);
4491 waitForIdle();
Erik Klinee89953b2018-01-11 16:11:10 +09004492 // CS tells netd about the empty DNS config for this network.
Erik Kline79c6d052018-03-21 07:18:33 -07004493 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4494 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
Erik Klinee89953b2018-01-11 16:11:10 +09004495 reset(mNetworkManagementService);
4496
4497 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4498 mCellNetworkAgent.sendLinkProperties(cellLp);
4499 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004500 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004501 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07004502 eq(""), tlsServers.capture());
Erik Klinee89953b2018-01-11 16:11:10 +09004503 assertEquals(1, mStringArrayCaptor.getValue().length);
4504 assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004505 // Opportunistic mode.
4506 assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
Erik Klinee89953b2018-01-11 16:11:10 +09004507 reset(mNetworkManagementService);
4508
4509 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4510 mCellNetworkAgent.sendLinkProperties(cellLp);
4511 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004512 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004513 anyInt(), mStringArrayCaptor.capture(), any(), any(),
Erik Kline79c6d052018-03-21 07:18:33 -07004514 eq(""), tlsServers.capture());
Erik Kline117e7f32018-03-04 21:01:01 +09004515 assertEquals(2, mStringArrayCaptor.getValue().length);
4516 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4517 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004518 // Opportunistic mode.
4519 assertEquals(2, tlsServers.getValue().length);
4520 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4521 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline117e7f32018-03-04 21:01:01 +09004522 reset(mNetworkManagementService);
4523
4524 final String TLS_SPECIFIER = "tls.example.com";
4525 final String TLS_SERVER6 = "2001:db8:53::53";
4526 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4527 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004528 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4529 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4530
Erik Kline117e7f32018-03-04 21:01:01 +09004531 waitForIdle();
Erik Kline79c6d052018-03-21 07:18:33 -07004532 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
Erik Kline117e7f32018-03-04 21:01:01 +09004533 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4534 eq(TLS_SPECIFIER), eq(TLS_SERVERS));
Erik Klinee89953b2018-01-11 16:11:10 +09004535 assertEquals(2, mStringArrayCaptor.getValue().length);
4536 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4537 new String[]{"2001:db8::1", "192.0.2.1"}));
4538 reset(mNetworkManagementService);
4539 }
4540
Erik Kline79c6d052018-03-21 07:18:33 -07004541 @Test
4542 public void testPrivateDnsSettingsChange() throws Exception {
4543 final String[] EMPTY_STRING_ARRAY = new String[0];
4544 ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
4545
4546 // Clear any interactions that occur as a result of CS starting up.
4547 reset(mNetworkManagementService);
4548
4549 // The default on Android is opportunistic mode ("Automatic").
4550 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4551
dalyk1fcb7392018-03-05 12:42:22 -05004552 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4553 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4554 .addTransportType(TRANSPORT_CELLULAR).build();
4555 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4556
Erik Kline79c6d052018-03-21 07:18:33 -07004557 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4558 waitForIdle();
4559 // CS tells netd about the empty DNS config for this network.
4560 verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
4561 anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
4562 verifyNoMoreInteractions(mNetworkManagementService);
4563
4564 final LinkProperties cellLp = new LinkProperties();
4565 cellLp.setInterfaceName(MOBILE_IFNAME);
4566 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4567 // "is-reachable" testing in order to not program netd with unreachable
4568 // nameservers that it might try repeated to validate.
4569 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4570 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4571 MOBILE_IFNAME));
4572 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4573 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4574 MOBILE_IFNAME));
4575 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4576 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4577
4578 mCellNetworkAgent.sendLinkProperties(cellLp);
4579 mCellNetworkAgent.connect(false);
4580 waitForIdle();
4581 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4582 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4583 eq(""), tlsServers.capture());
4584 assertEquals(2, mStringArrayCaptor.getValue().length);
4585 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4586 new String[]{"2001:db8::1", "192.0.2.1"}));
4587 // Opportunistic mode.
4588 assertEquals(2, tlsServers.getValue().length);
4589 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4590 new String[]{"2001:db8::1", "192.0.2.1"}));
4591 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004592 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4593 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4594 mCellNetworkAgent);
4595 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4596 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004597 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004598 cellNetworkCallback.assertNoCallback();
4599 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4600 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004601
4602 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
4603 verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
4604 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4605 eq(""), eq(EMPTY_STRING_ARRAY));
4606 assertEquals(2, mStringArrayCaptor.getValue().length);
4607 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4608 new String[]{"2001:db8::1", "192.0.2.1"}));
4609 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004610 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004611
4612 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4613 verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
4614 anyInt(), mStringArrayCaptor.capture(), any(), any(),
4615 eq(""), tlsServers.capture());
4616 assertEquals(2, mStringArrayCaptor.getValue().length);
4617 assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
4618 new String[]{"2001:db8::1", "192.0.2.1"}));
4619 assertEquals(2, tlsServers.getValue().length);
4620 assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
4621 new String[]{"2001:db8::1", "192.0.2.1"}));
4622 reset(mNetworkManagementService);
dalyk1fcb7392018-03-05 12:42:22 -05004623 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004624
dalyk1fcb7392018-03-05 12:42:22 -05004625 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4626 // Can't test dns configuration for strict mode without properly mocking
4627 // out the DNS lookups, but can test that LinkProperties is updated.
4628 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4629 mCellNetworkAgent);
4630 cellNetworkCallback.assertNoCallback();
4631 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4632 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
4633 }
4634
4635 @Test
4636 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4637 // The default on Android is opportunistic mode ("Automatic").
4638 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4639
4640 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4641 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4642 .addTransportType(TRANSPORT_CELLULAR).build();
4643 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4644
4645 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4646 waitForIdle();
4647 LinkProperties lp = new LinkProperties();
4648 mCellNetworkAgent.sendLinkProperties(lp);
4649 mCellNetworkAgent.connect(false);
4650 waitForIdle();
4651 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
4652 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
4653 mCellNetworkAgent);
4654 CallbackInfo cbi = cellNetworkCallback.expectCallback(
4655 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004656 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004657 cellNetworkCallback.assertNoCallback();
4658 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4659 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4660 Set<InetAddress> dnsServers = new HashSet<>();
4661 checkDnsServers(cbi.arg, dnsServers);
4662
4663 // Send a validation event for a server that is not part of the current
4664 // resolver config. The validation event should be ignored.
4665 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4666 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4667 cellNetworkCallback.assertNoCallback();
4668
4669 // Add a dns server to the LinkProperties.
4670 LinkProperties lp2 = new LinkProperties(lp);
4671 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4672 mCellNetworkAgent.sendLinkProperties(lp2);
4673 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4674 mCellNetworkAgent);
4675 cellNetworkCallback.assertNoCallback();
4676 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4677 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4678 dnsServers.add(InetAddress.getByName("145.100.185.16"));
4679 checkDnsServers(cbi.arg, dnsServers);
4680
4681 // Send a validation event containing a hostname that is not part of
4682 // the current resolver config. The validation event should be ignored.
4683 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4684 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4685 cellNetworkCallback.assertNoCallback();
4686
4687 // Send a validation event where validation failed.
4688 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4689 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4690 cellNetworkCallback.assertNoCallback();
4691
4692 // Send a validation event where validation succeeded for a server in
4693 // the current resolver config. A LinkProperties callback with updated
4694 // private dns fields should be sent.
4695 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4696 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
4697 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4698 mCellNetworkAgent);
4699 cellNetworkCallback.assertNoCallback();
4700 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4701 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4702 checkDnsServers(cbi.arg, dnsServers);
4703
4704 // The private dns fields in LinkProperties should be preserved when
4705 // the network agent sends unrelated changes.
4706 LinkProperties lp3 = new LinkProperties(lp2);
4707 lp3.setMtu(1300);
4708 mCellNetworkAgent.sendLinkProperties(lp3);
4709 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4710 mCellNetworkAgent);
4711 cellNetworkCallback.assertNoCallback();
4712 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
4713 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4714 checkDnsServers(cbi.arg, dnsServers);
4715 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
4716
4717 // Removing the only validated server should affect the private dns
4718 // fields in LinkProperties.
4719 LinkProperties lp4 = new LinkProperties(lp3);
4720 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4721 mCellNetworkAgent.sendLinkProperties(lp4);
4722 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4723 mCellNetworkAgent);
4724 cellNetworkCallback.assertNoCallback();
4725 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
4726 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
4727 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
4728 checkDnsServers(cbi.arg, dnsServers);
4729 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07004730 }
4731
Rubin Xu1bb5c082017-09-05 18:40:49 +01004732 private void checkDirectlyConnectedRoutes(Object callbackObj,
4733 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4734 assertTrue(callbackObj instanceof LinkProperties);
4735 LinkProperties lp = (LinkProperties) callbackObj;
4736
4737 Set<RouteInfo> expectedRoutes = new ArraySet<>();
4738 expectedRoutes.addAll(otherRoutes);
4739 for (LinkAddress address : linkAddresses) {
4740 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4741 // Duplicates in linkAddresses are considered failures
4742 assertTrue(expectedRoutes.add(localRoute));
4743 }
4744 List<RouteInfo> observedRoutes = lp.getRoutes();
4745 assertEquals(expectedRoutes.size(), observedRoutes.size());
4746 assertTrue(observedRoutes.containsAll(expectedRoutes));
4747 }
4748
dalyk1fcb7392018-03-05 12:42:22 -05004749 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4750 assertTrue(callbackObj instanceof LinkProperties);
4751 LinkProperties lp = (LinkProperties) callbackObj;
4752 assertEquals(dnsServers.size(), lp.getDnsServers().size());
4753 assertTrue(lp.getDnsServers().containsAll(dnsServers));
4754 }
4755
Hugo Benichifed512a2017-06-26 10:06:49 +09004756 private static <T> void assertEmpty(T[] ts) {
4757 int length = ts.length;
4758 assertEquals("expected empty array, but length was " + length, 0, length);
4759 }
4760
4761 private static <T> void assertLength(int expected, T[] got) {
4762 int length = got.length;
4763 assertEquals(String.format("expected array of length %s, but length was %s for %s",
4764 expected, length, Arrays.toString(got)), expected, length);
4765 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09004766
4767 private static <T> void assertException(Runnable block, Class<T> expected) {
4768 try {
4769 block.run();
4770 fail("Expected exception of type " + expected);
4771 } catch (Exception got) {
4772 if (!got.getClass().equals(expected)) {
4773 fail("Expected exception of type " + expected + " but got " + got);
4774 }
4775 return;
4776 }
4777 }
Chalard Jean0b214af2018-01-12 17:22:49 +09004778
4779 @Test
4780 public void testVpnNetworkActive() {
4781 final int uid = Process.myUid();
4782
4783 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004784 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004785 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4786 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004787 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004788 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4789 final NetworkRequest genericRequest = new NetworkRequest.Builder()
4790 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09004791 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4792 .addTransportType(TRANSPORT_WIFI).build();
4793 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09004794 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09004795 .addTransportType(TRANSPORT_VPN).build();
4796 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09004797 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004798 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4799 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004800 mCm.registerDefaultNetworkCallback(defaultCallback);
4801 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004802
4803 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4804 mWiFiNetworkAgent.connect(false);
4805
4806 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004807 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004808 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004809 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004810 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004811 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004812
4813 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4814 final ArraySet<UidRange> ranges = new ArraySet<>();
4815 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004816 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4817 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004818 // VPN networks do not satisfy the default request and are automatically validated
4819 // by NetworkMonitor
Lorenzo Colittied3168e2019-01-23 17:54:08 +09004820 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004821 vpnNetworkAgent.setNetworkValid();
4822
Chalard Jean0b214af2018-01-12 17:22:49 +09004823 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004824 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004825 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09004826
4827 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004828 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004829 wifiNetworkCallback.assertNoCallback();
4830 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004831 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
4832 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004833
4834 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004835 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09004836 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004837 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4838 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004839
4840 ranges.clear();
4841 vpnNetworkAgent.setUids(ranges);
4842
4843 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004844 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004845 wifiNetworkCallback.assertNoCallback();
4846 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4847
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004848 // TODO : The default network callback should actually get a LOST call here (also see the
4849 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
4850 // ranges at all when determining whether a network should be rematched. In practice, VPNs
4851 // can't currently update their UIDs without disconnecting, so this does not matter too
4852 // much, but that is the reason the test here has to check for an update to the
4853 // capabilities instead of the expected LOST then AVAILABLE.
4854 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
4855
Chalard Jean0b214af2018-01-12 17:22:49 +09004856 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004857 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08004858 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09004859
4860 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004861 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004862 wifiNetworkCallback.assertNoCallback();
4863 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004864 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
4865 // happen outside of the test, ConnectivityService does not rematch callbacks.
4866 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004867
4868 mWiFiNetworkAgent.disconnect();
4869
4870 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004871 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004872 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
4873 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004874 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004875
4876 vpnNetworkAgent.disconnect();
4877
4878 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004879 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004880 wifiNetworkCallback.assertNoCallback();
4881 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004882 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4883 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004884
4885 mCm.unregisterNetworkCallback(genericNetworkCallback);
4886 mCm.unregisterNetworkCallback(wifiNetworkCallback);
4887 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004888 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004889 }
Chalard Jean26400492018-04-18 20:18:38 +09004890
4891 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08004892 public void testVpnWithoutInternet() {
Chalard Jean26400492018-04-18 20:18:38 +09004893 final int uid = Process.myUid();
4894
4895 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4896 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09004897
4898 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4899 mWiFiNetworkAgent.connect(true);
4900
4901 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4902 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4903
4904 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4905 final ArraySet<UidRange> ranges = new ArraySet<>();
4906 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004907 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4908 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004909 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004910 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09004911
4912 defaultCallback.assertNoCallback();
4913 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4914
4915 vpnNetworkAgent.disconnect();
4916 defaultCallback.assertNoCallback();
4917
Varun Anand4fa80e82019-02-06 10:13:38 -08004918 mCm.unregisterNetworkCallback(defaultCallback);
4919 }
4920
4921 @Test
4922 public void testVpnWithInternet() {
4923 final int uid = Process.myUid();
4924
4925 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
4926 mCm.registerDefaultNetworkCallback(defaultCallback);
4927
4928 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4929 mWiFiNetworkAgent.connect(true);
4930
4931 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
4932 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4933
4934 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4935 final ArraySet<UidRange> ranges = new ArraySet<>();
4936 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004937 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4938 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09004939 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004940 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004941
Chalard Jean26400492018-04-18 20:18:38 +09004942 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4943 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
4944
4945 vpnNetworkAgent.disconnect();
4946 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
4947 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
4948
Chalard Jean26400492018-04-18 20:18:38 +09004949 mCm.unregisterNetworkCallback(defaultCallback);
4950 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004951
4952 @Test
4953 public void testVpnSetUnderlyingNetworks() {
4954 final int uid = Process.myUid();
4955
4956 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
4957 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
4958 .removeCapability(NET_CAPABILITY_NOT_VPN)
4959 .addTransportType(TRANSPORT_VPN)
4960 .build();
4961 NetworkCapabilities nc;
4962 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
4963 vpnNetworkCallback.assertNoCallback();
4964
4965 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
4966 final ArraySet<UidRange> ranges = new ArraySet<>();
4967 ranges.add(new UidRange(uid, uid));
4968 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4969 mMockVpn.connect();
4970 mMockVpn.setUids(ranges);
4971 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
4972
4973 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
4974 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
4975 assertTrue(nc.hasTransport(TRANSPORT_VPN));
4976 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
4977 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
4978 // For safety reasons a VPN without underlying networks is considered metered.
4979 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
4980
4981 // Connect cell and use it as an underlying network.
4982 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4983 mCellNetworkAgent.connect(true);
4984
4985 mService.setUnderlyingNetworksForVpn(
4986 new Network[] { mCellNetworkAgent.getNetwork() });
4987
4988 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
4989 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
4990 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
4991 vpnNetworkAgent);
4992
4993 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4994 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
4995 mWiFiNetworkAgent.connect(true);
4996
4997 mService.setUnderlyingNetworksForVpn(
4998 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
4999
5000 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5001 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5002 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5003 vpnNetworkAgent);
5004
5005 // Don't disconnect, but note the VPN is not using wifi any more.
5006 mService.setUnderlyingNetworksForVpn(
5007 new Network[] { mCellNetworkAgent.getNetwork() });
5008
5009 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5010 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5011 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5012 vpnNetworkAgent);
5013
5014 // Use Wifi but not cell. Note the VPN is now unmetered.
5015 mService.setUnderlyingNetworksForVpn(
5016 new Network[] { mWiFiNetworkAgent.getNetwork() });
5017
5018 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5019 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5020 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5021 vpnNetworkAgent);
5022
5023 // Use both again.
5024 mService.setUnderlyingNetworksForVpn(
5025 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5026
5027 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5028 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5029 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5030 vpnNetworkAgent);
5031
Chalard Jean6b65ec72018-05-18 22:02:56 +09005032 // Disconnect cell. Receive update without even removing the dead network from the
5033 // underlying networks – it's dead anyway. Not metered any more.
5034 mCellNetworkAgent.disconnect();
5035 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5036 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5037 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5038 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005039
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005040 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005041 mWiFiNetworkAgent.disconnect();
5042 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5043 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005044 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09005045 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005046
5047 mMockVpn.disconnect();
5048 }
junyulai4a192e22018-06-13 15:00:37 +08005049
Mike Yuf9729752018-08-17 15:22:05 +08005050 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005051 public void testNullUnderlyingNetworks() {
5052 final int uid = Process.myUid();
5053
5054 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5055 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5056 .removeCapability(NET_CAPABILITY_NOT_VPN)
5057 .addTransportType(TRANSPORT_VPN)
5058 .build();
5059 NetworkCapabilities nc;
5060 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5061 vpnNetworkCallback.assertNoCallback();
5062
5063 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5064 final ArraySet<UidRange> ranges = new ArraySet<>();
5065 ranges.add(new UidRange(uid, uid));
5066 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5067 mMockVpn.connect();
5068 mMockVpn.setUids(ranges);
5069 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5070
5071 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5072 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5073 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5074 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5075 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5076 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5077 // In case of no default network, VPN is considered metered.
5078 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5079
5080 // Connect to Cell; Cell is the default network.
5081 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5082 mCellNetworkAgent.connect(true);
5083
5084 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5085 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5086 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5087 vpnNetworkAgent);
5088
5089 // Connect to WiFi; WiFi is the new default.
5090 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5091 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5092 mWiFiNetworkAgent.connect(true);
5093
5094 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5095 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5096 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5097 vpnNetworkAgent);
5098
5099 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5100 // the capabilities.
5101 mCellNetworkAgent.disconnect();
5102
5103 // Disconnect wifi too. Now we have no default network.
5104 mWiFiNetworkAgent.disconnect();
5105
5106 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5107 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5108 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5109 vpnNetworkAgent);
5110
5111 mMockVpn.disconnect();
5112 }
5113
5114 @Test
Varun Anandc51b06d2019-02-25 17:22:02 -08005115 public void testIsActiveNetworkMeteredOverWifi() {
5116 // Returns true by default when no network is available.
5117 assertTrue(mCm.isActiveNetworkMetered());
5118 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5119 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5120 mWiFiNetworkAgent.connect(true);
5121 waitForIdle();
5122
5123 assertFalse(mCm.isActiveNetworkMetered());
5124 }
5125
5126 @Test
5127 public void testIsActiveNetworkMeteredOverCell() {
5128 // Returns true by default when no network is available.
5129 assertTrue(mCm.isActiveNetworkMetered());
5130 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5131 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5132 mCellNetworkAgent.connect(true);
5133 waitForIdle();
5134
5135 assertTrue(mCm.isActiveNetworkMetered());
5136 }
5137
5138 @Test
5139 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
5140 // Returns true by default when no network is available.
5141 assertTrue(mCm.isActiveNetworkMetered());
5142 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5143 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5144 mCellNetworkAgent.connect(true);
5145 waitForIdle();
5146 assertTrue(mCm.isActiveNetworkMetered());
5147
5148 // Connect VPN network. By default it is using current default network (Cell).
5149 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5150 final ArraySet<UidRange> ranges = new ArraySet<>();
5151 final int uid = Process.myUid();
5152 ranges.add(new UidRange(uid, uid));
5153 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5154 mMockVpn.setUids(ranges);
5155 vpnNetworkAgent.connect(true);
5156 mMockVpn.connect();
5157 waitForIdle();
5158 // Ensure VPN is now the active network.
5159 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5160
5161 // Expect VPN to be metered.
5162 assertTrue(mCm.isActiveNetworkMetered());
5163
5164 // Connect WiFi.
5165 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5166 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5167 mWiFiNetworkAgent.connect(true);
5168 waitForIdle();
5169 // VPN should still be the active network.
5170 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5171
5172 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5173 assertFalse(mCm.isActiveNetworkMetered());
5174
5175 // Disconnecting Cell should not affect VPN's meteredness.
5176 mCellNetworkAgent.disconnect();
5177 waitForIdle();
5178
5179 assertFalse(mCm.isActiveNetworkMetered());
5180
5181 // Disconnect WiFi; Now there is no platform default network.
5182 mWiFiNetworkAgent.disconnect();
5183 waitForIdle();
5184
5185 // VPN without any underlying networks is treated as metered.
5186 assertTrue(mCm.isActiveNetworkMetered());
5187
5188 vpnNetworkAgent.disconnect();
5189 mMockVpn.disconnect();
5190 }
5191
5192 @Test
5193 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
5194 // Returns true by default when no network is available.
5195 assertTrue(mCm.isActiveNetworkMetered());
5196 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5197 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5198 mCellNetworkAgent.connect(true);
5199 waitForIdle();
5200 assertTrue(mCm.isActiveNetworkMetered());
5201
5202 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5203 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5204 mWiFiNetworkAgent.connect(true);
5205 waitForIdle();
5206 assertFalse(mCm.isActiveNetworkMetered());
5207
5208 // Connect VPN network.
5209 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5210 final ArraySet<UidRange> ranges = new ArraySet<>();
5211 final int uid = Process.myUid();
5212 ranges.add(new UidRange(uid, uid));
5213 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5214 mMockVpn.setUids(ranges);
5215 vpnNetworkAgent.connect(true);
5216 mMockVpn.connect();
5217 waitForIdle();
5218 // Ensure VPN is now the active network.
5219 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5220 // VPN is using Cell
5221 mService.setUnderlyingNetworksForVpn(
5222 new Network[] { mCellNetworkAgent.getNetwork() });
5223 waitForIdle();
5224
5225 // Expect VPN to be metered.
5226 assertTrue(mCm.isActiveNetworkMetered());
5227
5228 // VPN is now using WiFi
5229 mService.setUnderlyingNetworksForVpn(
5230 new Network[] { mWiFiNetworkAgent.getNetwork() });
5231 waitForIdle();
5232
5233 // Expect VPN to be unmetered
5234 assertFalse(mCm.isActiveNetworkMetered());
5235
5236 // VPN is using Cell | WiFi.
5237 mService.setUnderlyingNetworksForVpn(
5238 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5239 waitForIdle();
5240
5241 // Expect VPN to be metered.
5242 assertTrue(mCm.isActiveNetworkMetered());
5243
5244 // VPN is using WiFi | Cell.
5245 mService.setUnderlyingNetworksForVpn(
5246 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5247 waitForIdle();
5248
5249 // Order should not matter and VPN should still be metered.
5250 assertTrue(mCm.isActiveNetworkMetered());
5251
5252 // VPN is not using any underlying networks.
5253 mService.setUnderlyingNetworksForVpn(new Network[0]);
5254 waitForIdle();
5255
5256 // VPN without underlying networks is treated as metered.
5257 assertTrue(mCm.isActiveNetworkMetered());
5258
5259 vpnNetworkAgent.disconnect();
5260 mMockVpn.disconnect();
5261 }
5262
5263 @Test
5264 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
5265 // Returns true by default when no network is available.
5266 assertTrue(mCm.isActiveNetworkMetered());
5267 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5268 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5269 mWiFiNetworkAgent.connect(true);
5270 waitForIdle();
5271 assertFalse(mCm.isActiveNetworkMetered());
5272
5273 // Connect VPN network.
5274 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5275 final ArraySet<UidRange> ranges = new ArraySet<>();
5276 final int uid = Process.myUid();
5277 ranges.add(new UidRange(uid, uid));
5278 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5279 mMockVpn.setUids(ranges);
5280 vpnNetworkAgent.connect(true);
5281 mMockVpn.connectAsAlwaysMetered();
5282 waitForIdle();
5283 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5284
5285 // VPN is tracking current platform default (WiFi).
5286 mService.setUnderlyingNetworksForVpn(null);
5287 waitForIdle();
5288
5289 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5290 assertTrue(mCm.isActiveNetworkMetered());
5291
5292 // VPN explicitly declares WiFi as its underlying network.
5293 mService.setUnderlyingNetworksForVpn(
5294 new Network[] { mWiFiNetworkAgent.getNetwork() });
5295 waitForIdle();
5296
5297 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5298 assertTrue(mCm.isActiveNetworkMetered());
5299
5300 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5301 // anyways suppose to be metered.
5302 mWiFiNetworkAgent.disconnect();
5303 waitForIdle();
5304
5305 assertTrue(mCm.isActiveNetworkMetered());
5306
5307 vpnNetworkAgent.disconnect();
5308 }
5309
5310 @Test
Mike Yuf9729752018-08-17 15:22:05 +08005311 public void testNetworkBlockedStatus() {
5312 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5313 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5314 .addTransportType(TRANSPORT_CELLULAR)
5315 .build();
5316 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5317
5318 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5319 mCellNetworkAgent.connect(true);
5320 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5321
5322 mService.setUidRulesChanged(RULE_REJECT_ALL);
5323 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5324
5325 // ConnectivityService should cache it not to invoke the callback again.
5326 mService.setUidRulesChanged(RULE_REJECT_METERED);
5327 cellNetworkCallback.assertNoCallback();
5328
5329 mService.setUidRulesChanged(RULE_NONE);
5330 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5331
5332 mService.setUidRulesChanged(RULE_REJECT_METERED);
5333 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5334
5335 // Restrict the network based on UID rule and NOT_METERED capability change.
5336 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5337 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5338 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5339 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5340 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5341 mCellNetworkAgent);
5342 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5343 mService.setUidRulesChanged(RULE_ALLOW_METERED);
5344 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5345
5346 mService.setUidRulesChanged(RULE_NONE);
5347 cellNetworkCallback.assertNoCallback();
5348
5349 // Restrict the network based on BackgroundRestricted.
5350 mService.setRestrictBackgroundChanged(true);
5351 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5352 mService.setRestrictBackgroundChanged(true);
5353 cellNetworkCallback.assertNoCallback();
5354 mService.setRestrictBackgroundChanged(false);
5355 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5356 cellNetworkCallback.assertNoCallback();
5357
5358 mCm.unregisterNetworkCallback(cellNetworkCallback);
5359 }
5360
5361 @Test
5362 public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5363 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5364 mCm.registerDefaultNetworkCallback(defaultCallback);
5365
5366 // No Networkcallbacks invoked before any network is active.
5367 mService.setUidRulesChanged(RULE_REJECT_ALL);
5368 mService.setUidRulesChanged(RULE_NONE);
5369 mService.setUidRulesChanged(RULE_REJECT_METERED);
5370 defaultCallback.assertNoCallback();
5371
5372 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5373 mCellNetworkAgent.connect(true);
5374 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5375 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5376
5377 // Allow to use the network after switching to NOT_METERED network.
5378 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5379 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5380 mWiFiNetworkAgent.connect(true);
5381 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5382
5383 // Switch to METERED network. Restrict the use of the network.
5384 mWiFiNetworkAgent.disconnect();
5385 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5386 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5387
5388 // Network becomes NOT_METERED.
5389 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5390 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5391 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5392
5393 // Verify there's no Networkcallbacks invoked after data saver on/off.
5394 mService.setRestrictBackgroundChanged(true);
5395 mService.setRestrictBackgroundChanged(false);
5396 defaultCallback.assertNoCallback();
5397
5398 mCellNetworkAgent.disconnect();
5399 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5400 defaultCallback.assertNoCallback();
5401
5402 mCm.unregisterNetworkCallback(defaultCallback);
5403 }
5404
junyulai4a192e22018-06-13 15:00:37 +08005405 /**
5406 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5407 */
5408 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5409 InterfaceConfiguration cfg = new InterfaceConfiguration();
5410 cfg.setHardwareAddress("11:22:33:44:55:66");
5411 cfg.setLinkAddress(la);
5412 return cfg;
5413 }
5414
5415 /**
5416 * Make expected stack link properties, copied from Nat464Xlat.
5417 */
5418 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5419 LinkAddress clatAddress = la;
5420 LinkProperties stacked = new LinkProperties();
5421 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5422 RouteInfo ipv4Default = new RouteInfo(
5423 new LinkAddress(Inet4Address.ANY, 0),
5424 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5425 stacked.addRoute(ipv4Default);
5426 stacked.addLinkAddress(clatAddress);
5427 return stacked;
5428 }
5429
5430 @Test
5431 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
5432 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5433 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005434 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5435 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5436
junyulai4a192e22018-06-13 15:00:37 +08005437 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5438 .addTransportType(TRANSPORT_CELLULAR)
5439 .addCapability(NET_CAPABILITY_INTERNET)
5440 .build();
5441 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5442 mCm.registerNetworkCallback(networkRequest, networkCallback);
5443
Lorenzo Colittid593e292019-02-19 13:21:56 +09005444 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005445 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005446 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005447 final LinkProperties cellLp = new LinkProperties();
5448 cellLp.setInterfaceName(MOBILE_IFNAME);
5449 cellLp.addLinkAddress(myIpv6);
5450 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5451 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5452 reset(mNetworkManagementService);
5453 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5454 .thenReturn(getClatInterfaceConfig(myIpv4));
5455
Lorenzo Colittid593e292019-02-19 13:21:56 +09005456 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005457 mCellNetworkAgent.sendLinkProperties(cellLp);
5458 mCellNetworkAgent.connect(true);
5459 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005460 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005461
Lorenzo Colittid593e292019-02-19 13:21:56 +09005462 // Switching default network updates TCP buffer sizes.
5463 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5464
5465 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5466 // the NAT64 prefix was removed because one was never discovered.
5467 cellLp.addLinkAddress(myIpv4);
5468 mCellNetworkAgent.sendLinkProperties(cellLp);
5469 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5470 verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
5471
5472 verifyNoMoreInteractions(mMockNetd);
5473 reset(mMockNetd);
5474
5475 // Remove IPv4 address. Expect prefix discovery to be started again.
5476 cellLp.removeLinkAddress(myIpv4);
5477 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5478 mCellNetworkAgent.sendLinkProperties(cellLp);
5479 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5480 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
5481
5482 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005483 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
5484 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005485 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5486 kNat64PrefixString, 96);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005487 LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
5488 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
5489 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5490 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5491 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5492
5493 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005494 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005495 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005496 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5497 .getStackedLinks();
5498 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5499
5500 // Change trivial linkproperties and see if stacked link is preserved.
5501 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5502 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005503 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5504
5505 List<LinkProperties> stackedLpsAfterChange =
5506 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5507 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5508 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5509
Lorenzo Colittid593e292019-02-19 13:21:56 +09005510 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5511 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005512 cellLp.addLinkAddress(myIpv4);
5513 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5514 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005515 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005516 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005517 verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005518
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005519 // As soon as stop is called, the linkproperties lose the stacked interface.
junyulai4a192e22018-06-13 15:00:37 +08005520 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
5521 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005522 LinkProperties expected = new LinkProperties(cellLp);
5523 expected.setNat64Prefix(kNat64Prefix);
5524 assertEquals(expected, actualLpAfterIpv4);
5525 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
junyulai4a192e22018-06-13 15:00:37 +08005526
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005527 // The interface removed callback happens but has no effect after stop is called.
5528 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5529 networkCallback.assertNoCallback();
5530
Lorenzo Colittid593e292019-02-19 13:21:56 +09005531 verifyNoMoreInteractions(mMockNetd);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005532 reset(mMockNetd);
5533
Lorenzo Colittid593e292019-02-19 13:21:56 +09005534 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5535 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5536 kNat64PrefixString, 96);
5537 networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
5538 mCellNetworkAgent);
5539
5540 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005541 cellLp.removeLinkAddress(myIpv4);
5542 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5543 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5544 mCellNetworkAgent.sendLinkProperties(cellLp);
5545 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005546 verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
5547 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5548 kNat64PrefixString, 96);
5549 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005550 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5551
Lorenzo Colittid593e292019-02-19 13:21:56 +09005552
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005553 // Clat iface comes up. Expect stacked link to be added.
5554 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005555 networkCallback.expectLinkPropertiesLike(
5556 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005557 mCellNetworkAgent);
5558
5559 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005560 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5561 kNat64PrefixString, 96);
5562 networkCallback.expectLinkPropertiesLike(
5563 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005564 mCellNetworkAgent);
5565 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
5566 networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
5567 mCellNetworkAgent);
5568
5569 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005570 mCellNetworkAgent.disconnect();
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005571 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5572 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005573 mCm.unregisterNetworkCallback(networkCallback);
5574 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005575
5576 @Test
5577 public void testDataActivityTracking() throws RemoteException {
5578 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5579 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5580 .addCapability(NET_CAPABILITY_INTERNET)
5581 .build();
5582 mCm.registerNetworkCallback(networkRequest, networkCallback);
5583
5584 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5585 final LinkProperties cellLp = new LinkProperties();
5586 cellLp.setInterfaceName(MOBILE_IFNAME);
5587 mCellNetworkAgent.sendLinkProperties(cellLp);
5588 reset(mNetworkManagementService);
5589 mCellNetworkAgent.connect(true);
5590 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5591 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5592 eq(ConnectivityManager.TYPE_MOBILE));
5593
5594 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5595 final LinkProperties wifiLp = new LinkProperties();
5596 wifiLp.setInterfaceName(WIFI_IFNAME);
5597 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5598
5599 // Network switch
5600 reset(mNetworkManagementService);
5601 mWiFiNetworkAgent.connect(true);
5602 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5603 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
5604 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5605 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
5606 eq(ConnectivityManager.TYPE_WIFI));
5607 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
5608
5609 // Disconnect wifi and switch back to cell
5610 reset(mNetworkManagementService);
5611 mWiFiNetworkAgent.disconnect();
5612 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5613 assertNoCallbacks(networkCallback);
5614 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5615 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5616 eq(ConnectivityManager.TYPE_MOBILE));
5617
5618 // reconnect wifi
5619 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5620 wifiLp.setInterfaceName(WIFI_IFNAME);
5621 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5622 mWiFiNetworkAgent.connect(true);
5623 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5624 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
5625 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5626
5627 // Disconnect cell
5628 reset(mNetworkManagementService);
5629 mCellNetworkAgent.disconnect();
5630 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5631 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
5632 // sent as network being switched. Ensure rule removal for cell will not be triggered
5633 // unexpectedly before network being removed.
5634 waitForIdle();
5635 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
5636 verify(mNetworkManagementService, times(1)).removeNetwork(
5637 eq(mCellNetworkAgent.getNetwork().netId));
5638
5639 // Disconnect wifi
5640 ConditionVariable cv = waitForConnectivityBroadcasts(1);
5641 reset(mNetworkManagementService);
5642 mWiFiNetworkAgent.disconnect();
5643 waitFor(cv);
5644 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5645
5646 // Clean up
5647 mCm.unregisterNetworkCallback(networkCallback);
5648 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005649
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005650 private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005651 String[] values = tcpBufferSizes.split(",");
5652 String rmemValues = String.join(" ", values[0], values[1], values[2]);
5653 String wmemValues = String.join(" ", values[3], values[4], values[5]);
5654 waitForIdle();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005655 try {
5656 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
5657 } catch (RemoteException e) {
5658 fail("mMockNetd should never throw RemoteException");
5659 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005660 reset(mMockNetd);
5661 }
5662
5663 @Test
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005664 public void testTcpBufferReset() {
5665 final String testTcpBufferSizes = "1,2,3,4,5,6";
5666
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005667 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5668 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005669 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005670 mCellNetworkAgent.connect(false);
5671 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5672
5673 // Change link Properties should have updated tcp buffer size.
5674 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005675 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005676 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005677 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005678 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005679
5680 @Test
5681 public void testGetGlobalProxyForNetwork() {
5682 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5683 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5684 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5685 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
5686 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
5687 }
5688
5689 @Test
5690 public void testGetProxyForActiveNetwork() {
5691 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5692 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5693 mWiFiNetworkAgent.connect(true);
5694 waitForIdle();
5695 assertNull(mService.getProxyForNetwork(null));
5696
5697 final LinkProperties testLinkProperties = new LinkProperties();
5698 testLinkProperties.setHttpProxy(testProxyInfo);
5699
5700 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5701 waitForIdle();
5702
5703 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5704 }
5705
5706 @Test
5707 public void testGetProxyForVPN() {
5708 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5709
5710 // Set up a WiFi network with no proxy
5711 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5712 mWiFiNetworkAgent.connect(true);
5713 waitForIdle();
5714 assertNull(mService.getProxyForNetwork(null));
5715
5716 // Set up a VPN network with a proxy
5717 final int uid = Process.myUid();
5718 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5719 final ArraySet<UidRange> ranges = new ArraySet<>();
5720 ranges.add(new UidRange(uid, uid));
5721 mMockVpn.setUids(ranges);
5722 LinkProperties testLinkProperties = new LinkProperties();
5723 testLinkProperties.setHttpProxy(testProxyInfo);
5724 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5725 waitForIdle();
5726
5727 // Connect to VPN with proxy
5728 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5729 vpnNetworkAgent.connect(true);
5730 mMockVpn.connect();
5731 waitForIdle();
5732
5733 // Test that the VPN network returns a proxy, and the WiFi does not.
5734 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5735 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5736 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5737
5738 // Test that the VPN network returns no proxy when it is set to null.
5739 testLinkProperties.setHttpProxy(null);
5740 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5741 waitForIdle();
5742 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
5743 assertNull(mService.getProxyForNetwork(null));
5744
5745 // Set WiFi proxy and check that the vpn proxy is still null.
5746 testLinkProperties.setHttpProxy(testProxyInfo);
5747 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5748 waitForIdle();
5749 assertNull(mService.getProxyForNetwork(null));
5750
5751 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
5752 // correct proxy setting.
5753 vpnNetworkAgent.disconnect();
5754 waitForIdle();
5755 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5756 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
5757 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5758 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07005759}