blob: 73ee7f544b5f5b6b9c4ccdbedf234d72f15e5d33 [file] [log] [blame]
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Rubin Xu12384742019-04-24 03:05:12 -070019import static android.content.pm.PackageManager.GET_PERMISSIONS;
20import static android.content.pm.PackageManager.MATCH_ANY_USER;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -070021import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
Erik Klinef851d6d2015-04-20 16:03:48 +090022import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090023import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070024import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
25import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
26import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090027import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070028import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090029import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
30import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Hugo Benichi16f0a942017-06-20 14:07:59 +090031import static android.net.ConnectivityManager.TYPE_NONE;
Chalard Jeanf9861102019-05-10 04:33:43 -070032import static android.net.ConnectivityManager.TYPE_VPN;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070033import static android.net.ConnectivityManager.TYPE_WIFI;
Chiachang Wang8d573212019-05-23 22:57:18 -070034import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
35import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
36import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
37import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
38import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
39import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060040import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
41import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
42import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
43import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
44import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
45import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
46import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
47import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
48import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090052import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060053import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080054import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060055import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
57import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
58import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
59import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
60import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
61import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
62import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090063import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060064import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
65import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080066import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
67import static android.net.NetworkPolicyManager.RULE_NONE;
68import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
69import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Rubin Xu9a3f7242019-04-11 11:45:43 -070070import static android.net.RouteInfo.RTN_UNREACHABLE;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060071
72import static com.android.internal.util.TestUtils.waitForIdleHandler;
Chalard Jeanb72b62d2018-02-16 16:08:35 +090073import static com.android.internal.util.TestUtils.waitForIdleLooper;
junyulai7c469172019-01-16 20:23:34 +080074import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
Lorenzo Colitti83fa2582015-08-07 12:49:01 +090075
Rubin Xu9a3f7242019-04-11 11:45:43 -070076import static org.junit.Assert.assertArrayEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090077import static org.junit.Assert.assertEquals;
78import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080079import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090080import static org.junit.Assert.assertNotNull;
81import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060082import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090083import static org.junit.Assert.fail;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -070084import static org.mockito.ArgumentMatchers.anyString;
Rubin Xu9a3f7242019-04-11 11:45:43 -070085import static org.mockito.ArgumentMatchers.eq;
Erik Klinee89953b2018-01-11 16:11:10 +090086import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +090087import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060088import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090089import static org.mockito.Mockito.doAnswer;
90import static org.mockito.Mockito.doNothing;
Rubin Xu9a3f7242019-04-11 11:45:43 -070091import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -080092import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060093import static org.mockito.Mockito.never;
94import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +090095import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090096import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +090097import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060098import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -070099import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900100import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700101
junyulai7c469172019-01-16 20:23:34 +0800102import android.annotation.NonNull;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900103import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400104import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400105import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900106import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900107import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700108import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400109import android.content.Intent;
110import android.content.IntentFilter;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700111import android.content.pm.ApplicationInfo;
112import android.content.pm.PackageInfo;
Rubin Xu12384742019-04-24 03:05:12 -0700113import android.content.pm.PackageManager;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700114import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900115import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400116import android.net.ConnectivityManager;
117import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900118import android.net.ConnectivityManager.PacketKeepalive;
119import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900120import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900121import android.net.ConnectivityThread;
Luke Huang65914772019-03-16 00:31:46 +0800122import android.net.IDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800123import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900124import android.net.INetworkMonitor;
125import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800126import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700127import android.net.INetworkPolicyManager;
128import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800129import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900130import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800131import android.net.IpSecManager;
132import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900133import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700134import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700135import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400136import android.net.Network;
137import android.net.NetworkAgent;
138import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700139import android.net.NetworkFactory;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700140import android.net.NetworkInfo;
141import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400142import android.net.NetworkMisc;
143import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700144import android.net.NetworkSpecifier;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700145import android.net.NetworkStack;
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900146import android.net.NetworkStackClient;
Varun Anand02c50ef2019-02-07 14:13:13 -0800147import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100148import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000149import android.net.ProxyInfo;
Wayne Ma28417f42019-04-17 08:03:59 -0700150import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700151import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800152import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900153import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900154import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900155import android.net.shared.NetworkMonitorUtils;
156import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900157import android.net.util.MultinetworkPolicyTracker;
Rubin Xu12384742019-04-24 03:05:12 -0700158import android.os.Binder;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700159import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400160import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700161import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700162import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700163import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900164import android.os.Looper;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900165import android.os.Message;
Etan Cohena7434272017-04-03 12:17:51 -0700166import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800167import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700168import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000169import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800170import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900171import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900172import android.os.UserHandle;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700173import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900174import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800175import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900176import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800177import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100178import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700179import android.util.Log;
Etan Cohenae574a82019-01-08 12:09:18 -0800180import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700181
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800182import androidx.test.InstrumentationRegistry;
183import androidx.test.filters.SmallTest;
184import androidx.test.runner.AndroidJUnit4;
185
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900186import com.android.internal.net.VpnConfig;
Varun Anand02c50ef2019-02-07 14:13:13 -0800187import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900188import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900189import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900190import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900191import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900192import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900193import com.android.server.connectivity.DefaultNetworkMetrics;
194import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900195import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800196import com.android.server.connectivity.Nat464Xlat;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700197import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000198import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800199import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900200import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900201import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900202import com.android.server.net.NetworkPolicyManagerInternal;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400203
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900204import org.junit.After;
205import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900206import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900207import org.junit.Test;
208import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900209import org.mockito.ArgumentCaptor;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700210import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900211import org.mockito.Mock;
212import org.mockito.MockitoAnnotations;
213import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900214import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900215
junyulai0c666972019-03-04 22:45:36 +0800216import java.io.IOException;
217import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800218import java.net.Inet4Address;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700219import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700220import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900221import java.net.InetSocketAddress;
222import java.net.Socket;
junyulai4a192e22018-06-13 15:00:37 +0800223import java.net.UnknownHostException;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400224import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900225import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100226import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800227import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500228import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100229import java.util.List;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +0900230import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100231import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900232import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800233import java.util.concurrent.Executor;
junyulaie4135282019-01-03 18:50:15 +0800234import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800235import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900236import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900237import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700238import java.util.concurrent.atomic.AtomicBoolean;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900239import java.util.function.Predicate;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700240
241/**
242 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400243 *
244 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900245 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700246 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900247@RunWith(AndroidJUnit4.class)
248@SmallTest
249public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700250 private static final String TAG = "ConnectivityServiceTest";
251
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900252 private static final int TIMEOUT_MS = 500;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900253 private static final int TEST_LINGER_DELAY_MS = 250;
254 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
255 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
256 // timeout. For this, our assertions should run fast enough to leave less than
257 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
258 // supposedly fired, and the time we call expectCallback.
259 private final static int TEST_CALLBACK_TIMEOUT_MS = 200;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900260 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
261 // complete before callbacks are verified.
262 private final static int TEST_REQUEST_TIMEOUT_MS = 150;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900263
junyulai4a192e22018-06-13 15:00:37 +0800264 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700265 private static final String MOBILE_IFNAME = "test_rmnet_data0";
266 private static final String WIFI_IFNAME = "test_wlan0";
Luke Huang65914772019-03-16 00:31:46 +0800267 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700268
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900269 private MockContext mServiceContext;
Paul Jensencf4c2c62015-07-01 14:16:32 -0400270 private WrappedConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900271 private WrappedConnectivityManager mCm;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400272 private MockNetworkAgent mWiFiNetworkAgent;
273 private MockNetworkAgent mCellNetworkAgent;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900274 private MockNetworkAgent mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900275 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900276 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800277 private INetworkPolicyListener mPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700278
Hugo Benichi64901e52017-10-19 14:42:40 +0900279 @Mock IpConnectivityMetrics.Logger mMetricsService;
280 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900281 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600282 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800283 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800284 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800285 @Mock INetd mMockNetd;
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900286 @Mock NetworkStackClient mNetworkStack;
Rubin Xu12384742019-04-24 03:05:12 -0700287 @Mock PackageManager mPackageManager;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700288 @Mock UserManager mUserManager;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700289 @Mock NotificationManager mNotificationManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900290
Wayne Ma28417f42019-04-17 08:03:59 -0700291 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
292 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900293
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900294 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
295 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
296 // reflect the state of our test ConnectivityService.
297 private class WrappedConnectivityManager extends ConnectivityManager {
298 private Network mFakeBoundNetwork;
299
300 public synchronized boolean bindProcessToNetwork(Network network) {
301 mFakeBoundNetwork = network;
302 return true;
303 }
304
305 public synchronized Network getBoundNetworkForProcess() {
306 return mFakeBoundNetwork;
307 }
308
309 public WrappedConnectivityManager(Context context, ConnectivityService service) {
310 super(context, service);
311 }
312 }
313
Paul Jensend7b6ca92015-05-13 14:05:12 -0400314 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900315 private final MockContentResolver mContentResolver;
316
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900317 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900318 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900319
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900320 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400321 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900322
323 mResources = spy(base.getResources());
324 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
325 thenReturn(new String[] {
326 "wifi,1,1,1,-1,true",
327 "mobile,0,0,0,-1,true",
328 "mobile_mms,2,0,2,60000,true",
329 });
330
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900331 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900332 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400333 }
334
335 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900336 public void startActivityAsUser(Intent intent, UserHandle handle) {
337 mStartedActivities.offer(intent);
338 }
339
340 public Intent expectStartActivityIntent(int timeoutMs) {
341 Intent intent = null;
342 try {
343 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
344 } catch (InterruptedException e) {}
345 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
346 return intent;
347 }
348
349 public void expectNoStartActivityIntent(int timeoutMs) {
350 try {
351 assertNull("Received unexpected Intent to start activity",
352 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
353 } catch (InterruptedException e) {}
354 }
355
356 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900357 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900358 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700359 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900360 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Rubin Xu9a3f7242019-04-11 11:45:43 -0700361 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400362 return super.getSystemService(name);
363 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900364
365 @Override
366 public ContentResolver getContentResolver() {
367 return mContentResolver;
368 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900369
370 @Override
371 public Resources getResources() {
372 return mResources;
373 }
Rubin Xu12384742019-04-24 03:05:12 -0700374
375 @Override
376 public PackageManager getPackageManager() {
377 return mPackageManager;
378 }
Remi NGUYEN VAN45527792019-06-25 09:40:54 -0700379
380 @Override
381 public void enforceCallingOrSelfPermission(String permission, String message) {
382 // The mainline permission can only be held if signed with the network stack certificate
383 // Skip testing for this permission.
384 if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
385 // All other permissions should be held by the test or unnecessary: check as normal to
386 // make sure the code does not rely on unexpected permissions.
387 super.enforceCallingOrSelfPermission(permission, message);
388 }
389 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400390
Hugo Benichi669f0232017-06-29 22:58:39 +0900391 public void waitForIdle(int timeoutMsAsInt) {
392 long timeoutMs = timeoutMsAsInt;
Hugo Benichibb91c572017-05-22 10:44:02 +0900393 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
394 waitForIdle(mCellNetworkAgent, timeoutMs);
395 waitForIdle(mWiFiNetworkAgent, timeoutMs);
396 waitForIdle(mEthernetNetworkAgent, timeoutMs);
397 waitForIdleHandler(mService.mHandlerThread, timeoutMs);
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900398 waitForIdleLooper(ConnectivityThread.getInstanceLooper(), timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900399 }
400
Hugo Benichi669f0232017-06-29 22:58:39 +0900401 public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900402 if (agent == null) {
403 return;
404 }
405 waitForIdleHandler(agent.mHandlerThread, timeoutMs);
406 }
407
408 private void waitForIdle() {
409 waitForIdle(TIMEOUT_MS);
410 }
411
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900412 @Test
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900413 public void testWaitForIdle() {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900414 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
415
416 // Tests that waitForIdle returns immediately if the service is already idle.
417 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900418 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900419 }
420
421 // Bring up a network that we can use to send messages to ConnectivityService.
422 ConditionVariable cv = waitForConnectivityBroadcasts(1);
423 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
424 mWiFiNetworkAgent.connect(false);
425 waitFor(cv);
426 Network n = mWiFiNetworkAgent.getNetwork();
427 assertNotNull(n);
428
429 // Tests that calling waitForIdle waits for messages to be processed.
430 for (int i = 0; i < attempts; i++) {
431 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900432 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900433 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
434 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900435 }
436
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900437 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
438 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800439 @Ignore
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900440 public void verifyThatNotWaitingForIdleCausesRaceConditions() {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900441 // Bring up a network that we can use to send messages to ConnectivityService.
442 ConditionVariable cv = waitForConnectivityBroadcasts(1);
443 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
444 mWiFiNetworkAgent.connect(false);
445 waitFor(cv);
446 Network n = mWiFiNetworkAgent.getNetwork();
447 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900448
449 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900450 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900451 for (int i = 0; i < attempts; i++) {
452 mWiFiNetworkAgent.setSignalStrength(i);
453 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
454 // We hit a race condition, as expected. Pass the test.
455 return;
456 }
457 }
458
459 // No race? There is a bug in this test.
460 fail("expected race condition at least once in " + attempts + " attempts");
461 }
462
Paul Jensend7b6ca92015-05-13 14:05:12 -0400463 private class MockNetworkAgent {
Chiachang Wang8d573212019-05-23 22:57:18 -0700464 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
465 | NETWORK_VALIDATION_PROBE_HTTP
466 | NETWORK_VALIDATION_PROBE_HTTPS;
467 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
468 | NETWORK_VALIDATION_RESULT_VALID;
469 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
470 | NETWORK_VALIDATION_PROBE_FALLBACK
471 | NETWORK_VALIDATION_RESULT_PARTIAL;
472 private static final int VALIDATION_RESULT_INVALID = 0;
473
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900474 private final INetworkMonitor mNetworkMonitor;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400475 private final NetworkInfo mNetworkInfo;
476 private final NetworkCapabilities mNetworkCapabilities;
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900477 private final HandlerThread mHandlerThread;
Paul Jensene0988542015-06-25 15:30:08 -0400478 private final ConditionVariable mDisconnected = new ConditionVariable();
Paul Jensen232437312016-04-06 09:51:26 -0400479 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
Calvin On1f64f3f2016-10-11 15:10:46 -0700480 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
Paul Jensen3d911462015-06-12 06:40:24 -0400481 private int mScore;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400482 private NetworkAgent mNetworkAgent;
junyulai0c666972019-03-04 22:45:36 +0800483 private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
junyulai48eac1d42018-12-27 17:25:29 +0800484 private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900485 private Integer mExpectedKeepaliveSlot = null;
Paul Jensen232437312016-04-06 09:51:26 -0400486 // Contains the redirectUrl from networkStatus(). Before reading, wait for
487 // mNetworkStatusReceived.
488 private String mRedirectUrl;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400489
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900490 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8d573212019-05-23 22:57:18 -0700491 private int mNmValidationResult = VALIDATION_RESULT_BASE;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900492 private String mNmValidationRedirectUrl = null;
493 private boolean mNmProvNotificationRequested = false;
494
495 void setNetworkValid() {
Chiachang Wang8d573212019-05-23 22:57:18 -0700496 mNmValidationResult = VALIDATION_RESULT_VALID;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900497 mNmValidationRedirectUrl = null;
498 }
499
500 void setNetworkInvalid() {
Chiachang Wang8d573212019-05-23 22:57:18 -0700501 mNmValidationResult = VALIDATION_RESULT_INVALID;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900502 mNmValidationRedirectUrl = null;
503 }
504
505 void setNetworkPortal(String redirectUrl) {
506 setNetworkInvalid();
507 mNmValidationRedirectUrl = redirectUrl;
508 }
509
lucasline252a742019-03-12 13:08:03 +0800510 void setNetworkPartial() {
Chiachang Wang8d573212019-05-23 22:57:18 -0700511 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
512 mNmValidationRedirectUrl = null;
513 }
514
515 void setNetworkPartialValid() {
516 mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
lucasline252a742019-03-12 13:08:03 +0800517 mNmValidationRedirectUrl = null;
518 }
519
Paul Jensend7b6ca92015-05-13 14:05:12 -0400520 MockNetworkAgent(int transport) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100521 this(transport, new LinkProperties());
522 }
523
524 MockNetworkAgent(int transport, LinkProperties linkProperties) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400525 final int type = transportToLegacyType(transport);
Chalard Jeanf9861102019-05-10 04:33:43 -0700526 final String typeName = ConnectivityManager.getNetworkTypeName(type);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400527 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
528 mNetworkCapabilities = new NetworkCapabilities();
529 mNetworkCapabilities.addTransportType(transport);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400530 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900531 case TRANSPORT_ETHERNET:
532 mScore = 70;
533 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400534 case TRANSPORT_WIFI:
Paul Jensen3d911462015-06-12 06:40:24 -0400535 mScore = 60;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400536 break;
537 case TRANSPORT_CELLULAR:
Paul Jensen3d911462015-06-12 06:40:24 -0400538 mScore = 50;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400539 break;
Hugo Benichi16f0a942017-06-20 14:07:59 +0900540 case TRANSPORT_WIFI_AWARE:
541 mScore = 20;
542 break;
Chalard Jean0b214af2018-01-12 17:22:49 +0900543 case TRANSPORT_VPN:
Chalard Jeanb552c462018-02-21 18:43:54 +0900544 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
Chalard Jeandda156a2018-01-10 21:19:32 +0900545 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
Chalard Jean0b214af2018-01-12 17:22:49 +0900546 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400547 default:
548 throw new UnsupportedOperationException("unimplemented network type");
549 }
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900550 mHandlerThread = new HandlerThread("Mock-" + typeName);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900551 mHandlerThread.start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900552
553 mNetworkMonitor = mock(INetworkMonitor.class);
554 final Answer validateAnswer = inv -> {
555 new Thread(this::onValidationRequested).start();
556 return null;
557 };
558
559 try {
Remi NGUYEN VAN3962f672019-03-27 15:42:53 +0900560 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900561 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
562 } catch (RemoteException e) {
563 fail(e.getMessage());
564 }
565
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900566 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900567 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
568 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
569 doNothing().when(mNetworkStack).makeNetworkMonitor(
570 nmNetworkCaptor.capture(),
571 any() /* name */,
572 nmCbCaptor.capture());
573
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900574 mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
575 "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
Chalard Jean08577fc2018-05-02 21:14:54 +0900576 linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900577 @Override
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900578 public void unwanted() { mDisconnected.open(); }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900579
580 @Override
junyulaie4135282019-01-03 18:50:15 +0800581 public void startSocketKeepalive(Message msg) {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900582 int slot = msg.arg1;
583 if (mExpectedKeepaliveSlot != null) {
584 assertEquals((int) mExpectedKeepaliveSlot, slot);
585 }
junyulaie4135282019-01-03 18:50:15 +0800586 onSocketKeepaliveEvent(slot, mStartKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900587 }
588
589 @Override
junyulaie4135282019-01-03 18:50:15 +0800590 public void stopSocketKeepalive(Message msg) {
591 onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900592 }
Paul Jensen232437312016-04-06 09:51:26 -0400593
594 @Override
595 public void networkStatus(int status, String redirectUrl) {
596 mRedirectUrl = redirectUrl;
597 mNetworkStatusReceived.open();
598 }
Calvin On1f64f3f2016-10-11 15:10:46 -0700599
600 @Override
601 protected void preventAutomaticReconnect() {
602 mPreventReconnectReceived.open();
603 }
Mark Chiend0f8ca82019-04-29 09:46:04 -0700604
605 @Override
606 protected void addKeepalivePacketFilter(Message msg) {
607 Log.i(TAG, "Add keepalive packet filter.");
608 }
609
610 @Override
611 protected void removeKeepalivePacketFilter(Message msg) {
612 Log.i(TAG, "Remove keepalive packet filter.");
613 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400614 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900615
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900616 assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900617 mNmCallbacks = nmCbCaptor.getValue();
618
619 try {
620 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
621 } catch (RemoteException e) {
622 fail(e.getMessage());
623 }
624
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900625 // Waits for the NetworkAgent to be registered, which includes the creation of the
626 // NetworkMonitor.
Hugo Benichibb91c572017-05-22 10:44:02 +0900627 waitForIdle();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900628 }
629
630 private void onValidationRequested() {
631 try {
632 if (mNmProvNotificationRequested
Chiachang Wang6786252e2019-05-25 08:42:17 -0700633 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900634 mNmCallbacks.hideProvisioningNotification();
635 mNmProvNotificationRequested = false;
636 }
637
638 mNmCallbacks.notifyNetworkTested(
639 mNmValidationResult, mNmValidationRedirectUrl);
640
641 if (mNmValidationRedirectUrl != null) {
642 mNmCallbacks.showProvisioningNotification(
Remi NGUYEN VAN9c5d9642019-02-07 21:29:57 +0900643 "test_provisioning_notif_action", "com.android.test.package");
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900644 mNmProvNotificationRequested = true;
645 }
646 } catch (RemoteException e) {
647 fail(e.getMessage());
648 }
Paul Jensen3d911462015-06-12 06:40:24 -0400649 }
650
651 public void adjustScore(int change) {
652 mScore += change;
653 mNetworkAgent.sendNetworkScore(mScore);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400654 }
655
Chalard Jeanf9861102019-05-10 04:33:43 -0700656 public int getScore() {
657 return mScore;
658 }
659
Lorenzo Colitti02cc8392017-05-17 01:28:09 +0900660 public void explicitlySelected(boolean acceptUnvalidated) {
661 mNetworkAgent.explicitlySelected(acceptUnvalidated);
662 }
663
Paul Jensen85cf78e2015-06-25 13:25:07 -0400664 public void addCapability(int capability) {
665 mNetworkCapabilities.addCapability(capability);
666 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
667 }
668
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +0900669 public void removeCapability(int capability) {
670 mNetworkCapabilities.removeCapability(capability);
671 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
672 }
673
Chalard Jean0b214af2018-01-12 17:22:49 +0900674 public void setUids(Set<UidRange> uids) {
675 mNetworkCapabilities.setUids(uids);
676 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
677 }
678
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900679 public void setSignalStrength(int signalStrength) {
680 mNetworkCapabilities.setSignalStrength(signalStrength);
681 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
682 }
683
Etan Cohena7434272017-04-03 12:17:51 -0700684 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
685 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
Lorenzo Colitti6556a222017-04-03 17:46:35 +0900686 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
687 }
688
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900689 public void setNetworkCapabilities(NetworkCapabilities nc,
690 boolean sendToConnectivityService) {
691 mNetworkCapabilities.set(nc);
692 if (sendToConnectivityService) {
693 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
694 }
695 }
696
Paul Jensene0988542015-06-25 15:30:08 -0400697 public void connectWithoutInternet() {
698 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
699 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
700 }
701
Paul Jensend7b6ca92015-05-13 14:05:12 -0400702 /**
Paul Jensene0988542015-06-25 15:30:08 -0400703 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400704 * @param validated Indicate if network should pretend to be validated.
705 */
706 public void connect(boolean validated) {
Hugo Benichi16f0a942017-06-20 14:07:59 +0900707 connect(validated, true);
708 }
709
710 /**
711 * Transition this NetworkAgent to CONNECTED state.
712 * @param validated Indicate if network should pretend to be validated.
713 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
714 */
715 public void connect(boolean validated, boolean hasInternet) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +0900716 assertEquals("MockNetworkAgents can only be connected once",
717 mNetworkInfo.getDetailedState(), DetailedState.IDLE);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400718 assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
719
Paul Jensend7b6ca92015-05-13 14:05:12 -0400720 NetworkCallback callback = null;
721 final ConditionVariable validatedCv = new ConditionVariable();
722 if (validated) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900723 setNetworkValid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400724 NetworkRequest request = new NetworkRequest.Builder()
725 .addTransportType(mNetworkCapabilities.getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900726 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400727 .build();
728 callback = new NetworkCallback() {
729 public void onCapabilitiesChanged(Network network,
730 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400731 if (network.equals(getNetwork()) &&
732 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400733 validatedCv.open();
734 }
735 }
736 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400737 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400738 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900739 if (hasInternet) {
740 addCapability(NET_CAPABILITY_INTERNET);
741 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400742
Paul Jensene0988542015-06-25 15:30:08 -0400743 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400744
745 if (validated) {
746 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400747 waitFor(validatedCv);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900748 setNetworkInvalid();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400749 }
750
751 if (callback != null) mCm.unregisterNetworkCallback(callback);
752 }
753
Paul Jensen232437312016-04-06 09:51:26 -0400754 public void connectWithCaptivePortal(String redirectUrl) {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900755 setNetworkPortal(redirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400756 connect(false);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400757 }
758
lucasline252a742019-03-12 13:08:03 +0800759 public void connectWithPartialConnectivity() {
760 setNetworkPartial();
761 connect(false);
762 }
763
Erik Kline1d3db322017-02-28 16:20:20 +0900764 public void suspend() {
765 mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
766 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
767 }
768
Chalard Jean804b8fb2018-01-30 22:41:41 +0900769 public void resume() {
770 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
771 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
772 }
773
Paul Jensend7b6ca92015-05-13 14:05:12 -0400774 public void disconnect() {
775 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
776 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
777 }
778
779 public Network getNetwork() {
780 return new Network(mNetworkAgent.netId);
781 }
Paul Jensene0988542015-06-25 15:30:08 -0400782
Calvin On1f64f3f2016-10-11 15:10:46 -0700783 public ConditionVariable getPreventReconnectReceived() {
784 return mPreventReconnectReceived;
785 }
786
Paul Jensene0988542015-06-25 15:30:08 -0400787 public ConditionVariable getDisconnectedCV() {
788 return mDisconnected;
789 }
Paul Jensencf4c2c62015-07-01 14:16:32 -0400790
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900791 public void sendLinkProperties(LinkProperties lp) {
792 mNetworkAgent.sendLinkProperties(lp);
793 }
794
795 public void setStartKeepaliveError(int error) {
796 mStartKeepaliveError = error;
797 }
798
799 public void setStopKeepaliveError(int error) {
800 mStopKeepaliveError = error;
801 }
802
803 public void setExpectedKeepaliveSlot(Integer slot) {
804 mExpectedKeepaliveSlot = slot;
805 }
Paul Jensen232437312016-04-06 09:51:26 -0400806
807 public String waitForRedirectUrl() {
808 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
809 return mRedirectUrl;
810 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900811
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900812 public NetworkAgent getNetworkAgent() {
813 return mNetworkAgent;
814 }
815
Chalard Jean804b8fb2018-01-30 22:41:41 +0900816 public NetworkCapabilities getNetworkCapabilities() {
817 return mNetworkCapabilities;
818 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400819 }
820
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900821 /**
822 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
823 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean08577fc2018-05-02 21:14:54 +0900824 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900825 * expectRemoveRequests.
826 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700827 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400828 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
829 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400830 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700831
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900832 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean08577fc2018-05-02 21:14:54 +0900833 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
834 // once, then cause some other thread to add or remove requests, then call
835 // waitForRequests().
836 // It is not possible to wait for both add and remove requests. When adding, the queue
837 // contains the expected score. When removing, the value is unused, all matters is the
838 // number of objects in the queue.
839 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900840
841 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean08577fc2018-05-02 21:14:54 +0900842 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900843 private boolean mExpectingAdditions;
844
Etan Cohenae574a82019-01-08 12:09:18 -0800845 // Used to collect the networks requests managed by this factory. This is a duplicate of
846 // the internal information stored in the NetworkFactory (which is private).
847 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
848
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700849 public MockNetworkFactory(Looper looper, Context context, String logTag,
850 NetworkCapabilities filter) {
851 super(looper, context, logTag, filter);
Chalard Jean08577fc2018-05-02 21:14:54 +0900852 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700853 }
854
855 public int getMyRequestCount() {
856 return getRequestCount();
857 }
858
859 protected void startNetwork() {
860 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400861 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700862 }
863
864 protected void stopNetwork() {
865 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400866 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700867 }
868
869 public boolean getMyStartRequested() {
870 return mNetworkStarted.get();
871 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400872
873 public ConditionVariable getNetworkStartedCV() {
874 mNetworkStartedCV.close();
875 return mNetworkStartedCV;
876 }
877
878 public ConditionVariable getNetworkStoppedCV() {
879 mNetworkStoppedCV.close();
880 return mNetworkStoppedCV;
881 }
882
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900883 @Override
Chalard Jean08577fc2018-05-02 21:14:54 +0900884 protected void handleAddRequest(NetworkRequest request, int score,
885 int factorySerialNumber) {
886 synchronized (mExpectations) {
887 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900888
Chalard Jean08577fc2018-05-02 21:14:54 +0900889 assertNotNull("Added more requests than expected (" + request + " score : "
890 + score + ")", expectedScore);
891 // If we're expecting anything, we must be expecting additions.
892 if (!mExpectingAdditions) {
893 fail("Can't add requests while expecting requests to be removed");
894 }
895 if (expectedScore != score) {
896 fail("Expected score was " + expectedScore + " but actual was " + score
897 + " in added request");
898 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900899
Chalard Jean08577fc2018-05-02 21:14:54 +0900900 // Add the request.
Etan Cohenae574a82019-01-08 12:09:18 -0800901 mNetworkRequests.put(request.requestId, request);
Chalard Jean08577fc2018-05-02 21:14:54 +0900902 super.handleAddRequest(request, score, factorySerialNumber);
903 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900904 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400905 }
906
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900907 @Override
908 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean08577fc2018-05-02 21:14:54 +0900909 synchronized (mExpectations) {
910 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900911
Chalard Jean08577fc2018-05-02 21:14:54 +0900912 assertTrue("Removed more requests than expected", expectedScore != null);
913 // If we're expecting anything, we must be expecting removals.
914 if (mExpectingAdditions) {
915 fail("Can't remove requests while expecting requests to be added");
916 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900917
Chalard Jean08577fc2018-05-02 21:14:54 +0900918 // Remove the request.
Etan Cohenae574a82019-01-08 12:09:18 -0800919 mNetworkRequests.remove(request.requestId);
Chalard Jean08577fc2018-05-02 21:14:54 +0900920 super.handleRemoveRequest(request);
921 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900922 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400923 }
924
Etan Cohenae574a82019-01-08 12:09:18 -0800925 // Trigger releasing the request as unfulfillable
926 public void triggerUnfulfillable(NetworkRequest r) {
927 super.releaseRequestAsUnfulfillableByAnyFactory(r);
928 }
929
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900930 private void assertNoExpectations() {
Chalard Jean08577fc2018-05-02 21:14:54 +0900931 if (mExpectations.size() != 0) {
932 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900933 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400934 }
935
Chalard Jean08577fc2018-05-02 21:14:54 +0900936 // Expects that requests with the specified scores will be added.
937 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900938 assertNoExpectations();
939 mExpectingAdditions = true;
Chalard Jean08577fc2018-05-02 21:14:54 +0900940 for (int score : scores) {
941 mExpectations.add(score);
942 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400943 }
944
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900945 // Expects that count requests will be removed.
946 public void expectRemoveRequests(final int count) {
947 assertNoExpectations();
948 mExpectingAdditions = false;
Chalard Jean08577fc2018-05-02 21:14:54 +0900949 for (int i = 0; i < count; ++i) {
950 mExpectations.add(0); // For removals the score is ignored so any value will do.
951 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900952 }
953
954 // Waits for the expected request additions or removals to happen within a timeout.
955 public void waitForRequests() throws InterruptedException {
Chalard Jean08577fc2018-05-02 21:14:54 +0900956 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
957 synchronized (mExpectations) {
958 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
959 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
960 }
961 }
962 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900963 final String msg = count + " requests still not " +
964 (mExpectingAdditions ? "added" : "removed") +
965 " after " + TIMEOUT_MS + " ms";
966 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900967 }
968
Etan Cohenae574a82019-01-08 12:09:18 -0800969 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
970 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900971 waitForRequests();
972 assertEquals(count, getMyRequestCount());
Etan Cohenae574a82019-01-08 12:09:18 -0800973 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400974 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700975 }
976
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900977 private static Looper startHandlerThreadAndReturnLooper() {
978 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
979 handlerThread.start();
980 return handlerThread.getLooper();
981 }
982
983 private class MockVpn extends Vpn {
984 // TODO : the interactions between this mock and the mock network agent are too
985 // hard to get right at this moment, because it's unclear in which case which
986 // target needs to get a method call or both, and in what order. It's because
987 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
988 // parent class of MockVpn agent wants that responsibility.
989 // That being said inside the test it should be possible to make the interactions
990 // harder to get wrong with precise speccing, judicious comments, helper methods
991 // and a few sprinkled assertions.
992
993 private boolean mConnected = false;
994 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
995 // not inherit from NetworkAgent.
996 private MockNetworkAgent mMockNetworkAgent;
997
998 public MockVpn(int userId) {
999 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
1000 userId);
1001 }
1002
1003 public void setNetworkAgent(MockNetworkAgent agent) {
1004 waitForIdle(agent, TIMEOUT_MS);
1005 mMockNetworkAgent = agent;
1006 mNetworkAgent = agent.getNetworkAgent();
1007 mNetworkCapabilities.set(agent.getNetworkCapabilities());
1008 }
1009
1010 public void setUids(Set<UidRange> uids) {
1011 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -08001012 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001013 }
1014
1015 @Override
1016 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -08001017 if (mMockNetworkAgent == null) {
1018 return NETID_UNSET;
1019 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001020 return mMockNetworkAgent.getNetwork().netId;
1021 }
1022
1023 @Override
1024 public boolean appliesToUid(int uid) {
1025 return mConnected; // Trickery to simplify testing.
1026 }
1027
1028 @Override
1029 protected boolean isCallerEstablishedOwnerLocked() {
1030 return mConnected; // Similar trickery
1031 }
1032
Varun Anandc51b06d2019-02-25 17:22:02 -08001033 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001034 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1035 mConnected = true;
1036 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -08001037 mConfig.isMetered = isAlwaysMetered;
1038 }
1039
1040 public void connectAsAlwaysMetered() {
1041 connect(true /* isAlwaysMetered */);
1042 }
1043
1044 public void connect() {
1045 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001046 }
1047
1048 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001049 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1050 if (!mConnected) return null;
1051 super.updateCapabilities(defaultNetwork);
1052 // Because super.updateCapabilities will update the capabilities of the agent but
1053 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001054 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -08001055 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001056 }
1057
1058 private void copyCapabilitiesToNetworkAgent() {
1059 if (null != mMockNetworkAgent) {
1060 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1061 false /* sendToConnectivityService */);
1062 }
1063 }
1064
1065 public void disconnect() {
1066 mConnected = false;
1067 mConfig = null;
1068 }
1069 }
1070
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001071 private class FakeWakeupMessage extends WakeupMessage {
1072 private static final int UNREASONABLY_LONG_WAIT = 1000;
1073
1074 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
1075 super(context, handler, cmdName, cmd);
1076 }
1077
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001078 public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd,
1079 int arg1, int arg2, Object obj) {
1080 super(context, handler, cmdName, cmd, arg1, arg2, obj);
1081 }
1082
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001083 @Override
1084 public void schedule(long when) {
1085 long delayMs = when - SystemClock.elapsedRealtime();
1086 if (delayMs < 0) delayMs = 0;
1087 if (delayMs > UNREASONABLY_LONG_WAIT) {
1088 fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
1089 "ms into the future: " + delayMs);
1090 }
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001091 Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
1092 mHandler.sendMessageDelayed(msg, delayMs);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001093 }
1094
1095 @Override
1096 public void cancel() {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001097 mHandler.removeMessages(mCmd, mObj);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001098 }
1099
1100 @Override
1101 public void onAlarm() {
1102 throw new AssertionError("Should never happen. Update this fake.");
1103 }
1104 }
1105
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001106 private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
Hugo Benichi53d83d52016-11-15 13:42:34 +09001107 public volatile boolean configRestrictsAvoidBadWifi;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001108 public volatile int configMeteredMultipathPreference;
Paul Jensencf4c2c62015-07-01 14:16:32 -04001109
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001110 public WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001111 super(c, h, r);
1112 }
1113
1114 @Override
1115 public boolean configRestrictsAvoidBadWifi() {
1116 return configRestrictsAvoidBadWifi;
1117 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001118
1119 @Override
1120 public int configMeteredMultipathPreference() {
1121 return configMeteredMultipathPreference;
1122 }
Erik Kline065ab6e2016-10-02 18:02:14 +09001123 }
1124
1125 private class WrappedConnectivityService extends ConnectivityService {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001126 public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001127 private MockableSystemProperties mSystemProperties;
Erik Kline065ab6e2016-10-02 18:02:14 +09001128
Paul Jensend7b6ca92015-05-13 14:05:12 -04001129 public WrappedConnectivityService(Context context, INetworkManagementService netManager,
Hugo Benichif9fdf872016-07-28 17:53:06 +09001130 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Luke Huang65914772019-03-16 00:31:46 +08001131 IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) {
Rubin Xu9a3f7242019-04-11 11:45:43 -07001132 super(context, netManager, statsService, policyManager, dnsResolver, log, netd);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001133 mNetd = netd;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001134 mLingerDelayMs = TEST_LINGER_DELAY_MS;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001135 }
1136
1137 @Override
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001138 protected MockableSystemProperties getSystemProperties() {
1139 // Minimal approach to overriding system properties: let most calls fall through to real
1140 // device values, and only override ones values that are important to this test.
1141 mSystemProperties = spy(new MockableSystemProperties());
1142 when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1143 when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1144 return mSystemProperties;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001145 }
Paul Jensen67b0b072015-06-10 11:22:17 -04001146
1147 @Override
Mike Yuf9729752018-08-17 15:22:05 +08001148 protected Tethering makeTethering() {
1149 return mock(Tethering.class);
1150 }
1151
1152 @Override
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001153 protected ProxyTracker makeProxyTracker() {
1154 return mock(ProxyTracker.class);
1155 }
1156
1157 @Override
Paul Jensen67b0b072015-06-10 11:22:17 -04001158 protected int reserveNetId() {
1159 while (true) {
1160 final int netId = super.reserveNetId();
1161
1162 // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
1163 // can have odd side-effects, like network validations succeeding.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001164 Context context = InstrumentationRegistry.getContext();
1165 final Network[] networks = ConnectivityManager.from(context).getAllNetworks();
Paul Jensen67b0b072015-06-10 11:22:17 -04001166 boolean overlaps = false;
1167 for (Network network : networks) {
1168 if (netId == network.netId) {
1169 overlaps = true;
1170 break;
1171 }
1172 }
1173 if (overlaps) continue;
1174
1175 return netId;
1176 }
1177 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001178
Irina Dumitrescu044a4362018-12-05 16:19:47 +00001179 @Override
1180 protected boolean queryUserAccess(int uid, int netId) {
1181 return true;
1182 }
1183
junyulai4a192e22018-06-13 15:00:37 +08001184 public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
1185 return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1186 }
1187
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001188 @Override
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001189 public MultinetworkPolicyTracker createMultinetworkPolicyTracker(
Erik Kline065ab6e2016-10-02 18:02:14 +09001190 Context c, Handler h, Runnable r) {
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001191 final WrappedMultinetworkPolicyTracker tracker = new WrappedMultinetworkPolicyTracker(c, h, r);
Erik Kline065ab6e2016-10-02 18:02:14 +09001192 return tracker;
1193 }
1194
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09001195 public WrappedMultinetworkPolicyTracker getMultinetworkPolicyTracker() {
1196 return (WrappedMultinetworkPolicyTracker) mMultinetworkPolicyTracker;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001197 }
1198
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001199 @Override
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +09001200 protected NetworkStackClient getNetworkStack() {
1201 return mNetworkStack;
1202 }
1203
1204 @Override
Erik Kline065ab6e2016-10-02 18:02:14 +09001205 public WakeupMessage makeWakeupMessage(
1206 Context context, Handler handler, String cmdName, int cmd, Object obj) {
1207 return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09001208 }
1209
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001210 @Override
1211 public boolean hasService(String name) {
1212 // Currenty, the only relevant service that ConnectivityService checks for is
1213 // ETHERNET_SERVICE.
1214 return Context.ETHERNET_SERVICE.equals(name);
1215 }
1216
Hugo Benichi64901e52017-10-19 14:42:40 +09001217 @Override
1218 protected IpConnectivityMetrics.Logger metricsLogger() {
1219 return mMetricsService;
1220 }
1221
dalyk1fcb7392018-03-05 12:42:22 -05001222 @Override
1223 protected void registerNetdEventCallback() {
1224 }
1225
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001226 public void mockVpn(int uid) {
1227 synchronized (mVpns) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001228 int userId = UserHandle.getUserId(uid);
1229 mMockVpn = new MockVpn(userId);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001230 // This has no effect unless the VPN is actually connected, because things like
1231 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1232 // netId, and check if that network is actually connected.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001233 mVpns.put(userId, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001234 }
1235 }
1236
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001237 public void waitForIdle(int timeoutMs) {
Hugo Benichiad4db4e2016-10-17 15:54:51 +09001238 waitForIdleHandler(mHandlerThread, timeoutMs);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001239 }
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001240
1241 public void waitForIdle() {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001242 waitForIdle(TIMEOUT_MS);
Lorenzo Colittie58961a2015-08-07 20:17:27 +09001243 }
Mike Yuf9729752018-08-17 15:22:05 +08001244
1245 public void setUidRulesChanged(int uidRules) {
1246 try {
1247 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1248 } catch (RemoteException ignored) {
1249 }
1250 }
1251
1252 public void setRestrictBackgroundChanged(boolean restrictBackground) {
1253 try {
1254 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1255 } catch (RemoteException ignored) {
1256 }
1257 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001258 }
1259
Paul Jensen3d911462015-06-12 06:40:24 -04001260 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001261 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1262 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001263 */
1264 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001265 if (conditionVariable.block(TIMEOUT_MS)) {
1266 return;
1267 }
1268 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001269 }
1270
Rubin Xu9a3f7242019-04-11 11:45:43 -07001271 private static final int VPN_USER = 0;
1272 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1273 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1274 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1275
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001276 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001277 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001278 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001279
Hugo Benichi64901e52017-10-19 14:42:40 +09001280 MockitoAnnotations.initMocks(this);
1281 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1282
Rubin Xu9a3f7242019-04-11 11:45:43 -07001283 when(mUserManager.getUsers(eq(true))).thenReturn(
1284 Arrays.asList(new UserInfo[] {
1285 new UserInfo(VPN_USER, "", 0),
1286 }));
Rubin Xu9a3f7242019-04-11 11:45:43 -07001287
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001288 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1289 // http://b/25897652 .
1290 if (Looper.myLooper() == null) {
1291 Looper.prepare();
1292 }
Rubin Xu12384742019-04-24 03:05:12 -07001293 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001294
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001295 FakeSettingsProvider.clearSettingsProvider();
1296 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1297 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001298 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1299 LocalServices.addService(
1300 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001301
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001302 mService = new WrappedConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001303 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001304 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001305 mNpm,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001306 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001307 mMockNetd,
1308 mMockDnsResolver);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001309
Mike Yuf9729752018-08-17 15:22:05 +08001310 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1311 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1312 verify(mNpm).registerListener(policyListenerCaptor.capture());
1313 mPolicyListener = policyListenerCaptor.getValue();
1314
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001315 // Create local CM before sending system ready so that we can answer
1316 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001317 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001318 mService.systemReady();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001319 mService.mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001320 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001321
1322 // Ensure that the default setting for Captive Portals is used for most tests
1323 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001324 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001325 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001326 }
1327
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001328 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001329 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001330 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001331 if (mCellNetworkAgent != null) {
1332 mCellNetworkAgent.disconnect();
1333 mCellNetworkAgent = null;
1334 }
1335 if (mWiFiNetworkAgent != null) {
1336 mWiFiNetworkAgent.disconnect();
1337 mWiFiNetworkAgent = null;
1338 }
1339 if (mEthernetNetworkAgent != null) {
1340 mEthernetNetworkAgent.disconnect();
1341 mEthernetNetworkAgent = null;
1342 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001343 FakeSettingsProvider.clearSettingsProvider();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001344 }
1345
Rubin Xu12384742019-04-24 03:05:12 -07001346 private void mockDefaultPackages() throws Exception {
1347 final String testPackageName = mContext.getPackageName();
1348 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1349 testPackageName, PackageManager.GET_PERMISSIONS);
1350 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1351 new String[] {testPackageName});
1352 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1353 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1354
1355 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1356 Arrays.asList(new PackageInfo[] {
1357 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1358 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1359 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1360 }));
1361 }
1362
1363 private static int transportToLegacyType(int transport) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001364 switch (transport) {
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001365 case TRANSPORT_ETHERNET:
1366 return TYPE_ETHERNET;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001367 case TRANSPORT_WIFI:
1368 return TYPE_WIFI;
1369 case TRANSPORT_CELLULAR:
1370 return TYPE_MOBILE;
Chalard Jeanf9861102019-05-10 04:33:43 -07001371 case TRANSPORT_VPN:
1372 return TYPE_VPN;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001373 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001374 return TYPE_NONE;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001375 }
1376 }
1377
1378 private void verifyActiveNetwork(int transport) {
1379 // Test getActiveNetworkInfo()
1380 assertNotNull(mCm.getActiveNetworkInfo());
1381 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1382 // Test getActiveNetwork()
1383 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001384 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001385 if (!NetworkCapabilities.isValidTransport(transport)) {
1386 throw new IllegalStateException("Unknown transport " + transport);
1387 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001388 switch (transport) {
1389 case TRANSPORT_WIFI:
1390 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1391 break;
1392 case TRANSPORT_CELLULAR:
1393 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1394 break;
1395 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001396 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001397 }
1398 // Test getNetworkInfo(Network)
1399 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001400 assertEquals(transportToLegacyType(transport),
1401 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001402 // Test getNetworkCapabilities(Network)
1403 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1404 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1405 }
1406
1407 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001408 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001409 // Test getActiveNetworkInfo()
1410 assertNull(mCm.getActiveNetworkInfo());
1411 // Test getActiveNetwork()
1412 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001413 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001414 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001415 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001416 }
1417
1418 /**
1419 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1420 * broadcasts are received.
1421 */
1422 private ConditionVariable waitForConnectivityBroadcasts(final int count) {
1423 final ConditionVariable cv = new ConditionVariable();
1424 mServiceContext.registerReceiver(new BroadcastReceiver() {
1425 private int remaining = count;
1426 public void onReceive(Context context, Intent intent) {
1427 if (--remaining == 0) {
1428 cv.open();
1429 mServiceContext.unregisterReceiver(this);
1430 }
1431 }
1432 }, new IntentFilter(CONNECTIVITY_ACTION));
1433 return cv;
1434 }
1435
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001436 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001437 public void testNetworkTypes() {
1438 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1439 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1440 // will fail. Failing here is much easier to debug.
1441 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1442 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001443 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1444 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1445
1446 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1447 // mocks, this assert exercises the ConnectivityService code path that ensures that
1448 // TYPE_ETHERNET is supported if the ethernet service is running.
1449 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001450 }
1451
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001452 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001453 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001454 verifyNoNetwork();
1455 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1456 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1457 assertNull(mCm.getActiveNetworkInfo());
1458 assertNull(mCm.getActiveNetwork());
1459 // Test bringing up validated cellular.
1460 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1461 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001462 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001463 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001464 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001465 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1466 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1467 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1468 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1469 // Test bringing up validated WiFi.
1470 cv = waitForConnectivityBroadcasts(2);
1471 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001472 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001473 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001474 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001475 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1476 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1477 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1478 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1479 // Test cellular linger timeout.
Lorenzo Colittid2706122017-01-30 17:45:49 +09001480 waitFor(mCellNetworkAgent.getDisconnectedCV());
Hugo Benichibb91c572017-05-22 10:44:02 +09001481 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001482 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001483 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001484 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001485 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1486 // Test WiFi disconnect.
1487 cv = waitForConnectivityBroadcasts(1);
1488 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001489 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001490 verifyNoNetwork();
1491 }
1492
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001493 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001494 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1495 // Test bringing up unvalidated WiFi
1496 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1497 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1498 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001499 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001500 verifyActiveNetwork(TRANSPORT_WIFI);
1501 // Test bringing up unvalidated cellular
1502 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1503 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001504 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001505 verifyActiveNetwork(TRANSPORT_WIFI);
1506 // Test cellular disconnect.
1507 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001508 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001509 verifyActiveNetwork(TRANSPORT_WIFI);
1510 // Test bringing up validated cellular
1511 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1512 cv = waitForConnectivityBroadcasts(2);
1513 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001514 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001515 verifyActiveNetwork(TRANSPORT_CELLULAR);
1516 // Test cellular disconnect.
1517 cv = waitForConnectivityBroadcasts(2);
1518 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001519 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001520 verifyActiveNetwork(TRANSPORT_WIFI);
1521 // Test WiFi disconnect.
1522 cv = waitForConnectivityBroadcasts(1);
1523 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001524 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001525 verifyNoNetwork();
1526 }
1527
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001528 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001529 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1530 // Test bringing up unvalidated cellular.
1531 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1532 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1533 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001534 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001535 verifyActiveNetwork(TRANSPORT_CELLULAR);
1536 // Test bringing up unvalidated WiFi.
1537 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1538 cv = waitForConnectivityBroadcasts(2);
1539 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001540 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001541 verifyActiveNetwork(TRANSPORT_WIFI);
1542 // Test WiFi disconnect.
1543 cv = waitForConnectivityBroadcasts(2);
1544 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001545 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001546 verifyActiveNetwork(TRANSPORT_CELLULAR);
1547 // Test cellular disconnect.
1548 cv = waitForConnectivityBroadcasts(1);
1549 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001550 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001551 verifyNoNetwork();
1552 }
1553
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001554 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001555 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001556 // Test bringing up unvalidated WiFi.
Paul Jensene0988542015-06-25 15:30:08 -04001557 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001558 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1559 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001560 waitFor(cv);
1561 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001562 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001563 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001564 // Test bringing up validated cellular.
1565 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001566 cv = waitForConnectivityBroadcasts(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001567 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001568 waitFor(cv);
1569 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001570 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1571 NET_CAPABILITY_VALIDATED));
1572 // Test cellular disconnect.
1573 cv = waitForConnectivityBroadcasts(2);
1574 mCellNetworkAgent.disconnect();
1575 waitFor(cv);
1576 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001577 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001578 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001579 NET_CAPABILITY_VALIDATED));
1580 }
1581
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001582 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001583 public void testCellularOutscoresWeakWifi() throws Exception {
1584 // Test bringing up validated cellular.
1585 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1586 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1587 mCellNetworkAgent.connect(true);
1588 waitFor(cv);
1589 verifyActiveNetwork(TRANSPORT_CELLULAR);
1590 // Test bringing up validated WiFi.
1591 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1592 cv = waitForConnectivityBroadcasts(2);
1593 mWiFiNetworkAgent.connect(true);
1594 waitFor(cv);
1595 verifyActiveNetwork(TRANSPORT_WIFI);
1596 // Test WiFi getting really weak.
1597 cv = waitForConnectivityBroadcasts(2);
1598 mWiFiNetworkAgent.adjustScore(-11);
1599 waitFor(cv);
1600 verifyActiveNetwork(TRANSPORT_CELLULAR);
1601 // Test WiFi restoring signal strength.
1602 cv = waitForConnectivityBroadcasts(2);
1603 mWiFiNetworkAgent.adjustScore(11);
1604 waitFor(cv);
1605 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001606 }
1607
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001608 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001609 public void testReapingNetwork() throws Exception {
1610 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1611 // Expect it to be torn down immediately because it satisfies no requests.
1612 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1613 ConditionVariable cv = mWiFiNetworkAgent.getDisconnectedCV();
1614 mWiFiNetworkAgent.connectWithoutInternet();
1615 waitFor(cv);
1616 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1617 // Expect it to be torn down immediately because it satisfies no requests.
1618 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1619 cv = mCellNetworkAgent.getDisconnectedCV();
1620 mCellNetworkAgent.connectWithoutInternet();
1621 waitFor(cv);
1622 // Test bringing up validated WiFi.
1623 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1624 cv = waitForConnectivityBroadcasts(1);
1625 mWiFiNetworkAgent.connect(true);
1626 waitFor(cv);
1627 verifyActiveNetwork(TRANSPORT_WIFI);
1628 // Test bringing up unvalidated cellular.
1629 // Expect it to be torn down because it could never be the highest scoring network
1630 // satisfying the default request even if it validated.
1631 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1632 cv = mCellNetworkAgent.getDisconnectedCV();
1633 mCellNetworkAgent.connect(false);
1634 waitFor(cv);
1635 verifyActiveNetwork(TRANSPORT_WIFI);
1636 cv = mWiFiNetworkAgent.getDisconnectedCV();
1637 mWiFiNetworkAgent.disconnect();
1638 waitFor(cv);
1639 }
1640
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001641 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001642 public void testCellularFallback() throws Exception {
1643 // Test bringing up validated cellular.
1644 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1645 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1646 mCellNetworkAgent.connect(true);
1647 waitFor(cv);
1648 verifyActiveNetwork(TRANSPORT_CELLULAR);
1649 // Test bringing up validated WiFi.
1650 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1651 cv = waitForConnectivityBroadcasts(2);
1652 mWiFiNetworkAgent.connect(true);
1653 waitFor(cv);
1654 verifyActiveNetwork(TRANSPORT_WIFI);
1655 // Reevaluate WiFi (it'll instantly fail DNS).
1656 cv = waitForConnectivityBroadcasts(2);
1657 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1658 NET_CAPABILITY_VALIDATED));
1659 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1660 // Should quickly fall back to Cellular.
1661 waitFor(cv);
1662 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1663 NET_CAPABILITY_VALIDATED));
1664 verifyActiveNetwork(TRANSPORT_CELLULAR);
1665 // Reevaluate cellular (it'll instantly fail DNS).
1666 cv = waitForConnectivityBroadcasts(2);
1667 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1668 NET_CAPABILITY_VALIDATED));
1669 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1670 // Should quickly fall back to WiFi.
1671 waitFor(cv);
1672 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1673 NET_CAPABILITY_VALIDATED));
1674 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1675 NET_CAPABILITY_VALIDATED));
1676 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001677 }
1678
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001679 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001680 public void testWiFiFallback() throws Exception {
1681 // Test bringing up unvalidated WiFi.
1682 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
1683 ConditionVariable cv = waitForConnectivityBroadcasts(1);
1684 mWiFiNetworkAgent.connect(false);
1685 waitFor(cv);
1686 verifyActiveNetwork(TRANSPORT_WIFI);
1687 // Test bringing up validated cellular.
1688 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
1689 cv = waitForConnectivityBroadcasts(2);
1690 mCellNetworkAgent.connect(true);
1691 waitFor(cv);
1692 verifyActiveNetwork(TRANSPORT_CELLULAR);
1693 // Reevaluate cellular (it'll instantly fail DNS).
1694 cv = waitForConnectivityBroadcasts(2);
1695 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1696 NET_CAPABILITY_VALIDATED));
1697 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1698 // Should quickly fall back to WiFi.
1699 waitFor(cv);
1700 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1701 NET_CAPABILITY_VALIDATED));
1702 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001703 }
1704
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001705 @Test
1706 public void testRequiresValidation() {
1707 assertTrue(NetworkMonitorUtils.isValidationRequired(
1708 mCm.getDefaultRequest().networkCapabilities));
1709 }
1710
Paul Jensen3d911462015-06-12 06:40:24 -04001711 enum CallbackState {
1712 NONE,
1713 AVAILABLE,
Erik Klineacdd6392016-07-07 16:50:58 +09001714 NETWORK_CAPABILITIES,
1715 LINK_PROPERTIES,
Erik Kline1d3db322017-02-28 16:20:20 +09001716 SUSPENDED,
Chalard Jean804b8fb2018-01-30 22:41:41 +09001717 RESUMED,
Paul Jensen3d911462015-06-12 06:40:24 -04001718 LOSING,
Erik Kline3841a482015-11-25 12:49:38 +09001719 LOST,
Mike Yuf9729752018-08-17 15:22:05 +08001720 UNAVAILABLE,
1721 BLOCKED_STATUS
Paul Jensen3d911462015-06-12 06:40:24 -04001722 }
1723
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001724 private static class CallbackInfo {
1725 public final CallbackState state;
1726 public final Network network;
1727 public final Object arg;
1728 public CallbackInfo(CallbackState s, Network n, Object o) {
1729 state = s; network = n; arg = o;
1730 }
1731 public String toString() {
Erik Kline1d3db322017-02-28 16:20:20 +09001732 return String.format("%s (%s) (%s)", state, network, arg);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001733 }
1734 @Override
1735 public boolean equals(Object o) {
1736 if (!(o instanceof CallbackInfo)) return false;
1737 // Ignore timeMs, since it's unpredictable.
1738 CallbackInfo other = (CallbackInfo) o;
1739 return (state == other.state) && Objects.equals(network, other.network);
1740 }
1741 @Override
1742 public int hashCode() {
1743 return Objects.hash(state, network);
1744 }
1745 }
1746
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001747 /**
1748 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1749 * this class receives, by calling expectCallback() exactly once each time a callback is
1750 * received. assertNoCallback may be called at any time.
1751 */
Paul Jensen3d911462015-06-12 06:40:24 -04001752 private class TestNetworkCallback extends NetworkCallback {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001753 private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001754 private Network mLastAvailableNetwork;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001755
Erik Klineacdd6392016-07-07 16:50:58 +09001756 protected void setLastCallback(CallbackState state, Network network, Object o) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001757 mCallbacks.offer(new CallbackInfo(state, network, o));
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001758 }
Paul Jensen3d911462015-06-12 06:40:24 -04001759
Erik Klineacdd6392016-07-07 16:50:58 +09001760 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001761 public void onAvailable(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001762 mLastAvailableNetwork = network;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001763 setLastCallback(CallbackState.AVAILABLE, network, null);
Paul Jensen3d911462015-06-12 06:40:24 -04001764 }
1765
Erik Klineacdd6392016-07-07 16:50:58 +09001766 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001767 public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
1768 setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
1769 }
1770
1771 @Override
1772 public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
1773 setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
1774 }
1775
1776 @Override
Erik Kline3841a482015-11-25 12:49:38 +09001777 public void onUnavailable() {
1778 setLastCallback(CallbackState.UNAVAILABLE, null, null);
1779 }
1780
1781 @Override
Erik Kline1d3db322017-02-28 16:20:20 +09001782 public void onNetworkSuspended(Network network) {
1783 setLastCallback(CallbackState.SUSPENDED, network, null);
1784 }
1785
1786 @Override
Chalard Jean804b8fb2018-01-30 22:41:41 +09001787 public void onNetworkResumed(Network network) {
1788 setLastCallback(CallbackState.RESUMED, network, null);
1789 }
1790
1791 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001792 public void onLosing(Network network, int maxMsToLive) {
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001793 setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
Paul Jensen3d911462015-06-12 06:40:24 -04001794 }
1795
Erik Klineacdd6392016-07-07 16:50:58 +09001796 @Override
Paul Jensen3d911462015-06-12 06:40:24 -04001797 public void onLost(Network network) {
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001798 mLastAvailableNetwork = null;
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001799 setLastCallback(CallbackState.LOST, network, null);
1800 }
1801
Mike Yuf9729752018-08-17 15:22:05 +08001802 @Override
1803 public void onBlockedStatusChanged(Network network, boolean blocked) {
1804 setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
1805 }
1806
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001807 public Network getLastAvailableNetwork() {
1808 return mLastAvailableNetwork;
1809 }
1810
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001811 CallbackInfo nextCallback(int timeoutMs) {
1812 CallbackInfo cb = null;
1813 try {
1814 cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
1815 } catch (InterruptedException e) {
1816 }
1817 if (cb == null) {
1818 // LinkedBlockingQueue.poll() returns null if it timeouts.
1819 fail("Did not receive callback after " + timeoutMs + "ms");
1820 }
1821 return cb;
1822 }
1823
Erik Kline1d3db322017-02-28 16:20:20 +09001824 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
1825 final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
1826 CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
Hugo Benichi4e1619f2016-12-20 17:05:06 +09001827 CallbackInfo actual = nextCallback(timeoutMs);
1828 assertEquals("Unexpected callback:", expected, actual);
Erik Kline1d3db322017-02-28 16:20:20 +09001829
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001830 if (state == CallbackState.LOSING) {
1831 String msg = String.format(
1832 "Invalid linger time value %d, must be between %d and %d",
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001833 actual.arg, 0, mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001834 int maxMsToLive = (Integer) actual.arg;
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001835 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001836 }
Erik Kline1d3db322017-02-28 16:20:20 +09001837
1838 return actual;
Erik Klinea2d29402016-03-16 15:31:39 +09001839 }
1840
Erik Kline1d3db322017-02-28 16:20:20 +09001841 CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001842 return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001843 }
1844
Hugo Benichi16f0a942017-06-20 14:07:59 +09001845 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001846 return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09001847 }
1848
1849 CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
1850 int timeLeft = timeoutMs;
1851 while (timeLeft > 0) {
1852 long start = SystemClock.elapsedRealtime();
1853 CallbackInfo info = nextCallback(timeLeft);
1854 if (fn.test(info)) {
1855 return info;
1856 }
1857 timeLeft -= (SystemClock.elapsedRealtime() - start);
1858 }
1859 fail("Did not receive expected callback after " + timeoutMs + "ms");
1860 return null;
1861 }
1862
Lorenzo Colitti27334542018-01-12 16:22:21 +09001863 // Expects onAvailable and the callbacks that follow it. These are:
1864 // - onSuspended, iff the network was suspended when the callbacks fire.
1865 // - onCapabilitiesChanged.
1866 // - onLinkPropertiesChanged.
Mike Yuf9729752018-08-17 15:22:05 +08001867 // - onBlockedStatusChanged.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001868 //
1869 // @param agent the network to expect the callbacks on.
1870 // @param expectSuspended whether to expect a SUSPENDED callback.
1871 // @param expectValidated the expected value of the VALIDATED capability in the
1872 // onCapabilitiesChanged callback.
1873 // @param timeoutMs how long to wait for the callbacks.
1874 void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
Mike Yuf9729752018-08-17 15:22:05 +08001875 boolean expectValidated, boolean expectBlocked, int timeoutMs) {
Erik Kline1d3db322017-02-28 16:20:20 +09001876 expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
Erik Klinec75d4fa2017-02-15 19:59:17 +09001877 if (expectSuspended) {
1878 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001879 }
Lorenzo Colitti27334542018-01-12 16:22:21 +09001880 if (expectValidated) {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001881 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001882 } else {
Chalard Jean1fa777d2018-02-16 16:07:53 +09001883 expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001884 }
Erik Klinec75d4fa2017-02-15 19:59:17 +09001885 expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
Mike Yuf9729752018-08-17 15:22:05 +08001886 expectBlockedStatusCallback(expectBlocked, agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001887 }
1888
Lorenzo Colitti27334542018-01-12 16:22:21 +09001889 // Expects the available callbacks (validated), plus onSuspended.
1890 void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
Mike Yuf9729752018-08-17 15:22:05 +08001891 expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001892 }
1893
Lorenzo Colitti27334542018-01-12 16:22:21 +09001894 void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001895 expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
1896 }
1897
1898 void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
1899 expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
Erik Kline1d3db322017-02-28 16:20:20 +09001900 }
1901
Lorenzo Colitti27334542018-01-12 16:22:21 +09001902 void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
Mike Yuf9729752018-08-17 15:22:05 +08001903 expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
1904 }
1905
1906 void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
1907 expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001908 }
1909
1910 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
1911 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
1912 // one we just sent.
1913 // TODO: this is likely a bug. Fix it and remove this method.
1914 void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001915 expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001916 NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001917 expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
Mike Yuf9729752018-08-17 15:22:05 +08001918 // Implicitly check the network is allowed to use.
1919 // TODO: should we need to consider if network is in blocked status in this case?
1920 expectBlockedStatusCallback(false, agent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001921 NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1922 assertEquals(nc1, nc2);
1923 }
1924
1925 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
1926 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
1927 // when a network connects and satisfies a callback, and then immediately validates.
1928 void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
1929 expectAvailableCallbacksUnvalidated(agent);
Erik Kline1d3db322017-02-28 16:20:20 +09001930 expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
1931 }
1932
Lorenzo Colitti27334542018-01-12 16:22:21 +09001933 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001934 return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001935 }
1936
1937 NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
1938 int timeoutMs) {
1939 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001940 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1941 assertTrue(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001942 return nc;
Erik Kline1d3db322017-02-28 16:20:20 +09001943 }
1944
Lorenzo Colitti27334542018-01-12 16:22:21 +09001945 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +09001946 return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
Chalard Jean1fa777d2018-02-16 16:07:53 +09001947 }
1948
1949 NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
1950 int timeoutMs) {
1951 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09001952 NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
1953 assertFalse(nc.hasCapability(capability));
Lorenzo Colitti27334542018-01-12 16:22:21 +09001954 return nc;
Paul Jensen3d911462015-06-12 06:40:24 -04001955 }
1956
Chalard Jean0b214af2018-01-12 17:22:49 +09001957 void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
1958 CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001959 assertTrue("Received capabilities don't match expectations : " + cbi.arg,
1960 fn.test((NetworkCapabilities) cbi.arg));
Chalard Jean0b214af2018-01-12 17:22:49 +09001961 }
1962
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09001963 void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
1964 CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
1965 assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
1966 fn.test((LinkProperties) cbi.arg));
1967 }
1968
Mike Yuf9729752018-08-17 15:22:05 +08001969 void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
1970 CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
1971 boolean actualBlocked = (boolean) cbi.arg;
1972 assertEquals(expectBlocked, actualBlocked);
1973 }
1974
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001975 void assertNoCallback() {
Hugo Benichibb91c572017-05-22 10:44:02 +09001976 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001977 CallbackInfo c = mCallbacks.peek();
1978 assertNull("Unexpected callback: " + c, c);
1979 }
1980 }
1981
1982 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1983 // only be declared in a static or top level type".
1984 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1985 for (TestNetworkCallback c : callbacks) {
1986 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001987 }
1988 }
1989
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001990 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001991 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001992 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001993 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1994 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001995 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1996 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001997 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1998 .addTransportType(TRANSPORT_WIFI).build();
1999 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2000 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002001 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002002 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
2003 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
2004
2005 // Test unvalidated networks
Paul Jensen3d911462015-06-12 06:40:24 -04002006 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2007 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2008 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002009 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2010 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002011 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2012 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002013 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002014
Paul Jensen3d911462015-06-12 06:40:24 -04002015 // This should not trigger spurious onAvailable() callbacks, b/21762680.
2016 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09002017 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002018 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002019 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2020
Paul Jensen3d911462015-06-12 06:40:24 -04002021 cv = waitForConnectivityBroadcasts(2);
2022 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2023 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002024 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2025 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002026 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2027 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002028 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002029
Paul Jensen3d911462015-06-12 06:40:24 -04002030 cv = waitForConnectivityBroadcasts(2);
2031 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002032 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2033 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09002034 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04002035 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002036 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002037
Paul Jensen3d911462015-06-12 06:40:24 -04002038 cv = waitForConnectivityBroadcasts(1);
2039 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002040 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2041 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002042 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002043 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002044
2045 // Test validated networks
Paul Jensen3d911462015-06-12 06:40:24 -04002046 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2047 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002048 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2049 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002050 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002051 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002052
Paul Jensen3d911462015-06-12 06:40:24 -04002053 // This should not trigger spurious onAvailable() callbacks, b/21762680.
2054 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09002055 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002056 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002057 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2058
Paul Jensen3d911462015-06-12 06:40:24 -04002059 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2060 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002061 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002062 genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002063 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002064 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002065 cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04002066 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002067 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002068
Paul Jensen3d911462015-06-12 06:40:24 -04002069 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002070 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2071 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2072 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002073
Paul Jensen3d911462015-06-12 06:40:24 -04002074 mCellNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002075 genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2076 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2077 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04002078 }
2079
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002080 @Test
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002081 public void testMultipleLingering() {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002082 // This test would be flaky with the default 120ms timer: that is short enough that
2083 // lingered networks are torn down before assertions can be run. We don't want to mock the
2084 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
2085 // in detecting races.
2086 mService.mLingerDelayMs = 300;
2087
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002088 NetworkRequest request = new NetworkRequest.Builder()
2089 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
2090 .build();
2091 TestNetworkCallback callback = new TestNetworkCallback();
2092 mCm.registerNetworkCallback(request, callback);
2093
2094 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2095 mCm.registerDefaultNetworkCallback(defaultCallback);
2096
2097 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2098 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2099 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2100
2101 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2102 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2103 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2104
2105 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002106 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2107 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002108 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002109 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002110
2111 mWiFiNetworkAgent.connect(true);
2112 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
2113 // We then get LOSING when wifi validates and cell is outscored.
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 Colitti7369d8d12016-06-28 21:28:28 +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.expectAvailableDoubleValidatedCallbacks(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 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002123 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002124 // TODO: Investigate sending validated before losing.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002125 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002126 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002127 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002128 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002129 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002130
2131 mEthernetNetworkAgent.disconnect();
2132 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2133 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002134 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002135 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002136
2137 for (int i = 0; i < 4; i++) {
2138 MockNetworkAgent oldNetwork, newNetwork;
2139 if (i % 2 == 0) {
2140 mWiFiNetworkAgent.adjustScore(-15);
2141 oldNetwork = mWiFiNetworkAgent;
2142 newNetwork = mCellNetworkAgent;
2143 } else {
2144 mWiFiNetworkAgent.adjustScore(15);
2145 oldNetwork = mCellNetworkAgent;
2146 newNetwork = mWiFiNetworkAgent;
2147
2148 }
2149 callback.expectCallback(CallbackState.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002150 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2151 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002152 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002153 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2154 }
2155 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2156
2157 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2158 // if the network is still up.
2159 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002160 // We expect a notification about the capabilities change, and nothing else.
2161 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2162 defaultCallback.assertNoCallback();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002163 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002164 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002165
2166 // Wifi no longer satisfies our listen, which is for an unmetered network.
2167 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002168 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2169
2170 // Disconnect our test networks.
2171 mWiFiNetworkAgent.disconnect();
2172 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002173 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002174 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002175 mCellNetworkAgent.disconnect();
2176 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002177 waitForIdle();
2178 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002179
2180 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002181 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002182
2183 // Check that a network is only lingered or torn down if it would not satisfy a request even
2184 // if it validated.
2185 request = new NetworkRequest.Builder().clearCapabilities().build();
2186 callback = new TestNetworkCallback();
2187
2188 mCm.registerNetworkCallback(request, callback);
2189
2190 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2191 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002192 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2193 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002194 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002195 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002196
2197 // Bring up wifi with a score of 20.
2198 // Cell stays up because it would satisfy the default request if it validated.
2199 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2200 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002201 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2202 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002203 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002204 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002205
2206 mWiFiNetworkAgent.disconnect();
2207 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2208 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002209 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002210 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002211 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002212
2213 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002214 // Cell is lingered because it would not satisfy any request, even if it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002215 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2216 mWiFiNetworkAgent.adjustScore(50);
2217 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002218 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002219 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002220 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002221 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002222 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002223
2224 // Tear down wifi.
2225 mWiFiNetworkAgent.disconnect();
2226 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2227 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002228 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002229 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002230 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002231
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002232 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2233 // it's arguably correct to linger it, since it was the default network before it validated.
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002234 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2235 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002236 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002237 // TODO: Investigate sending validated before losing.
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002238 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002239 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002240 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002241 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002242 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002243
2244 mWiFiNetworkAgent.disconnect();
2245 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002246 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002247 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002248 mCellNetworkAgent.disconnect();
2249 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2250 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002251 waitForIdle();
2252 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002253
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002254 // If a network is lingering, and we add and remove a request from it, resume lingering.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002255 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2256 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002257 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2258 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002259 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002260 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2261 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002262 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2263 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002264 // TODO: Investigate sending validated before losing.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002265 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002266 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002267 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002268
2269 NetworkRequest cellRequest = new NetworkRequest.Builder()
2270 .addTransportType(TRANSPORT_CELLULAR).build();
2271 NetworkCallback noopCallback = new NetworkCallback();
2272 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002273 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2274 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002275 mCm.unregisterNetworkCallback(noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002276 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002277
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002278 // Similar to the above: lingering can start even after the lingered request is removed.
2279 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002280 mWiFiNetworkAgent.disconnect();
2281 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002282 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002283 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002284 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002285
2286 // Cell is now the default network. Pin it with a cell-specific request.
2287 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2288 mCm.requestNetwork(cellRequest, noopCallback);
2289
2290 // Now connect wifi, and expect it to become the default network.
2291 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2292 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002293 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2294 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002295 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002296 // The default request is lingering on cell, but nothing happens to cell, and we send no
2297 // callbacks for it, because it's kept up by cellRequest.
2298 callback.assertNoCallback();
2299 // Now unregister cellRequest and expect cell to start lingering.
2300 mCm.unregisterNetworkCallback(noopCallback);
2301 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2302
2303 // Let linger run its course.
2304 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002305 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Hugo Benichidfb559a2016-12-20 14:57:49 +09002306 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002307
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002308 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2309 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2310 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002311 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002312 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2313 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002314 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002315 callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
2316 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002317 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2318 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002319 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002320
2321 // Let linger run its course.
2322 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
2323
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002324 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002325 mEthernetNetworkAgent.disconnect();
2326 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2327 defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
2328 trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002329
2330 mCm.unregisterNetworkCallback(callback);
2331 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002332 mCm.unregisterNetworkCallback(trackDefaultCallback);
2333 }
2334
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002335 @Test
Chalard Jean1fa777d2018-02-16 16:07:53 +09002336 public void testNetworkGoesIntoBackgroundAfterLinger() {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002337 setAlwaysOnNetworks(true);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002338 NetworkRequest request = new NetworkRequest.Builder()
2339 .clearCapabilities()
2340 .build();
2341 TestNetworkCallback callback = new TestNetworkCallback();
2342 mCm.registerNetworkCallback(request, callback);
2343
2344 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2345 mCm.registerDefaultNetworkCallback(defaultCallback);
2346
2347 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2348 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2349
2350 mCellNetworkAgent.connect(true);
2351 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2352 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2353
2354 // Wifi comes up and cell lingers.
2355 mWiFiNetworkAgent.connect(true);
2356 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2357 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2358 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2359 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2360
2361 // File a request for cellular, then release it.
2362 NetworkRequest cellRequest = new NetworkRequest.Builder()
2363 .addTransportType(TRANSPORT_CELLULAR).build();
2364 NetworkCallback noopCallback = new NetworkCallback();
2365 mCm.requestNetwork(cellRequest, noopCallback);
2366 mCm.unregisterNetworkCallback(noopCallback);
2367 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2368
2369 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002370 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002371 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2372 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2373 lingerTimeoutMs);
2374
2375 // Clean up.
2376 mCm.unregisterNetworkCallback(defaultCallback);
2377 mCm.unregisterNetworkCallback(callback);
2378 }
2379
2380 @Test
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002381 public void testExplicitlySelected() {
2382 NetworkRequest request = new NetworkRequest.Builder()
2383 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2384 .build();
2385 TestNetworkCallback callback = new TestNetworkCallback();
2386 mCm.registerNetworkCallback(request, callback);
2387
2388 // Bring up validated cell.
2389 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2390 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002391 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002392
2393 // Bring up unvalidated wifi with explicitlySelected=true.
2394 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2395 mWiFiNetworkAgent.explicitlySelected(false);
2396 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002397 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002398
2399 // Cell Remains the default.
2400 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2401
2402 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2403 // it's explicitly selected.
2404 mWiFiNetworkAgent.adjustScore(-40);
2405 mWiFiNetworkAgent.adjustScore(40);
2406 callback.assertNoCallback();
2407
2408 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2409 // wifi even though it's unvalidated.
2410 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
2411 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2412 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2413
2414 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2415 mWiFiNetworkAgent.disconnect();
2416 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2417 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2418 mWiFiNetworkAgent.explicitlySelected(false);
2419 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002420 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002421
2422 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2423 // network to disconnect.
2424 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
2425 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2426
2427 // Reconnect, again with explicitlySelected=true, but this time validate.
2428 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2429 mWiFiNetworkAgent.explicitlySelected(false);
2430 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002431 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002432 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2433 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2434 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2435
2436 // BUG: the network will no longer linger, even though it's validated and outscored.
2437 // TODO: fix this.
2438 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
2439 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002440 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002441 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2442 callback.assertNoCallback();
2443
2444 // Clean up.
2445 mWiFiNetworkAgent.disconnect();
2446 mCellNetworkAgent.disconnect();
2447 mEthernetNetworkAgent.disconnect();
2448
2449 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2450 callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
2451 callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002452 }
2453
Chalard Jean08577fc2018-05-02 21:14:54 +09002454 private int[] makeIntArray(final int size, final int value) {
2455 final int[] array = new int[size];
2456 Arrays.fill(array, value);
2457 return array;
2458 }
2459
Paul Jensen85cf78e2015-06-25 13:25:07 -04002460 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002461 // Verify NOT_RESTRICTED is set appropriately
2462 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2463 .build().networkCapabilities;
2464 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2465 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2466 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002467 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002468 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2469 } else {
2470 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2471 }
2472
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002473 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002474 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002475 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2476 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002477 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002478 mServiceContext, "testFactory", filter);
2479 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002480 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean08577fc2018-05-02 21:14:54 +09002481 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002482 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002483 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002484 int expectedRequestCount = 1;
2485 NetworkCallback networkCallback = null;
2486 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2487 // add one.
2488 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002489 assertFalse(testFactory.getMyStartRequested());
2490 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2491 networkCallback = new NetworkCallback();
Chalard Jean08577fc2018-05-02 21:14:54 +09002492 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002493 mCm.requestNetwork(request, networkCallback);
2494 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002495 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002496 }
Paul Jensen3d911462015-06-12 06:40:24 -04002497 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002498 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2499 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002500
Paul Jensen85cf78e2015-06-25 13:25:07 -04002501 // Now bring in a higher scored network.
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002502 MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002503 // Rather than create a validated network which complicates things by registering it's
2504 // own NetworkRequest during startup, just bump up the score to cancel out the
2505 // unvalidated penalty.
2506 testAgent.adjustScore(40);
2507 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002508
2509 // When testAgent connects, ConnectivityService will re-send us all current requests with
2510 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2511 // them.
Chalard Jean08577fc2018-05-02 21:14:54 +09002512 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002513 testAgent.connect(false);
2514 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002515 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002516 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002517 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002518
Paul Jensen85cf78e2015-06-25 13:25:07 -04002519 // Bring in a bunch of requests.
Chalard Jean08577fc2018-05-02 21:14:54 +09002520 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002521 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002522 ConnectivityManager.NetworkCallback[] networkCallbacks =
2523 new ConnectivityManager.NetworkCallback[10];
2524 for (int i = 0; i< networkCallbacks.length; i++) {
2525 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2526 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002527 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002528 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2529 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002530 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2531 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002532
Paul Jensen85cf78e2015-06-25 13:25:07 -04002533 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002534 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002535 for (int i = 0; i < networkCallbacks.length; i++) {
2536 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2537 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002538 testFactory.waitForNetworkRequests(expectedRequestCount);
2539 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002540
Paul Jensen85cf78e2015-06-25 13:25:07 -04002541 // Drop the higher scored network.
2542 cv = testFactory.getNetworkStartedCV();
Chalard Jean08577fc2018-05-02 21:14:54 +09002543 // With the default network disconnecting, the requests are sent with score 0 to factories.
2544 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002545 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002546 waitFor(cv);
Chalard Jean08577fc2018-05-02 21:14:54 +09002547 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002548 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2549 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002550
2551 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002552 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002553 handlerThread.quit();
2554 }
2555
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002556 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002557 public void testNetworkFactoryRequests() throws Exception {
2558 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2559 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2560 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2561 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2562 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2563 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2564 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2565 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2566 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2567 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2568 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2569 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2570 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2571 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2572 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2573 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2574 }
2575
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002576 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002577 public void testNoMutableNetworkRequests() throws Exception {
2578 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002579 NetworkRequest request1 = new NetworkRequest.Builder()
2580 .addCapability(NET_CAPABILITY_VALIDATED)
2581 .build();
2582 NetworkRequest request2 = new NetworkRequest.Builder()
2583 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2584 .build();
2585
2586 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
2587 assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
2588 assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
2589 assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
2590 assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002591 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002592
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002593 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002594 public void testMMSonWiFi() throws Exception {
2595 // Test bringing up cellular without MMS NetworkRequest gets reaped
2596 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2597 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2598 ConditionVariable cv = mCellNetworkAgent.getDisconnectedCV();
2599 mCellNetworkAgent.connectWithoutInternet();
2600 waitFor(cv);
Hugo Benichibb91c572017-05-22 10:44:02 +09002601 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002602 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002603 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002604
Paul Jensene0988542015-06-25 15:30:08 -04002605 // Test bringing up validated WiFi.
2606 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2607 cv = waitForConnectivityBroadcasts(1);
2608 mWiFiNetworkAgent.connect(true);
2609 waitFor(cv);
2610 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002611
Paul Jensene0988542015-06-25 15:30:08 -04002612 // Register MMS NetworkRequest
2613 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2614 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2615 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2616 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002617
Paul Jensene0988542015-06-25 15:30:08 -04002618 // Test bringing up unvalidated cellular with MMS
2619 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2620 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002621 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002622 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002623 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002624
Paul Jensene0988542015-06-25 15:30:08 -04002625 // Test releasing NetworkRequest disconnects cellular with MMS
2626 cv = mCellNetworkAgent.getDisconnectedCV();
2627 mCm.unregisterNetworkCallback(networkCallback);
2628 waitFor(cv);
2629 verifyActiveNetwork(TRANSPORT_WIFI);
2630 }
2631
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002632 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002633 public void testMMSonCell() throws Exception {
2634 // Test bringing up cellular without MMS
2635 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2636 ConditionVariable cv = waitForConnectivityBroadcasts(1);
2637 mCellNetworkAgent.connect(false);
2638 waitFor(cv);
2639 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002640
Paul Jensene0988542015-06-25 15:30:08 -04002641 // Register MMS NetworkRequest
2642 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2643 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2644 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2645 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002646
Paul Jensene0988542015-06-25 15:30:08 -04002647 // Test bringing up MMS cellular network
Paul Jensene0988542015-06-25 15:30:08 -04002648 MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2649 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2650 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002651 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002652 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002653
Paul Jensene0988542015-06-25 15:30:08 -04002654 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
2655 cv = mmsNetworkAgent.getDisconnectedCV();
2656 mCm.unregisterNetworkCallback(networkCallback);
2657 waitFor(cv);
2658 verifyActiveNetwork(TRANSPORT_CELLULAR);
2659 }
2660
lucaslinf3b59b32019-03-26 17:49:49 +08002661 @Test
lucasline252a742019-03-12 13:08:03 +08002662 public void testPartialConnectivity() {
2663 // Register network callback.
2664 NetworkRequest request = new NetworkRequest.Builder()
2665 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2666 .build();
2667 TestNetworkCallback callback = new TestNetworkCallback();
2668 mCm.registerNetworkCallback(request, callback);
2669
2670 // Bring up validated mobile data.
2671 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
2672 mCellNetworkAgent.connect(true);
2673 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2674
2675 // Bring up wifi with partial connectivity.
2676 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2677 mWiFiNetworkAgent.connectWithPartialConnectivity();
2678 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2679 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2680
2681 // Mobile data should be the default network.
2682 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2683 callback.assertNoCallback();
2684
lucaslinf3b59b32019-03-26 17:49:49 +08002685 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2686 // probe.
Chiachang Wang8d573212019-05-23 22:57:18 -07002687 mWiFiNetworkAgent.setNetworkPartialValid();
lucasline252a742019-03-12 13:08:03 +08002688 // If the user chooses yes to use this partial connectivity wifi, switch the default
2689 // network to wifi and check if wifi becomes valid or not.
2690 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2691 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002692 // If user accepts partial connectivity network,
2693 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002694 waitForIdle();
2695 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002696 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002697 } catch (RemoteException e) {
2698 fail(e.getMessage());
2699 }
lucaslinf3b59b32019-03-26 17:49:49 +08002700 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2701 // validated.
2702 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
lucasline252a742019-03-12 13:08:03 +08002703 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2704 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2705 mWiFiNetworkAgent);
2706 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2707 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2708
2709 // Disconnect and reconnect wifi with partial connectivity again.
2710 mWiFiNetworkAgent.disconnect();
2711 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2712 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2713 mWiFiNetworkAgent.connectWithPartialConnectivity();
2714 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2715 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2716
2717 // Mobile data should be the default network.
2718 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2719
2720 // If the user chooses no, disconnect wifi immediately.
2721 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2722 false /* always */);
2723 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2724
2725 // If user accepted partial connectivity before, and device reconnects to that network
2726 // again, but now the network has full connectivity. The network shouldn't contain
2727 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2728 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2729 // acceptUnvalidated is also used as setting for accepting partial networks.
2730 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
2731 mWiFiNetworkAgent.connect(true);
lucaslinf3b59b32019-03-26 17:49:49 +08002732 // If user accepted partial connectivity network before,
2733 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2734 // ConnectivityService#updateNetworkInfo().
2735 waitForIdle();
2736 try {
2737 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
2738 } catch (RemoteException e) {
2739 fail(e.getMessage());
2740 }
lucasline252a742019-03-12 13:08:03 +08002741 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2742 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
2743 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2744 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2745 // Wifi should be the default network.
2746 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2747 mWiFiNetworkAgent.disconnect();
2748 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2749
2750 // If user accepted partial connectivity before, and now the device reconnects to the
2751 // partial connectivity network. The network should be valid and contain
2752 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
2753 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2754 mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
lucaslinf3b59b32019-03-26 17:49:49 +08002755 // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
2756 // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
2757 // to ConnectivityService first then send VALID. Once NetworkMonitor support
2758 // multi-testResult, this test case also need to be changed to meet the new design.
lucasline252a742019-03-12 13:08:03 +08002759 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002760 // If user accepted partial connectivity network before,
2761 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2762 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002763 waitForIdle();
2764 try {
lucaslinf3b59b32019-03-26 17:49:49 +08002765 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
lucasline252a742019-03-12 13:08:03 +08002766 } catch (RemoteException e) {
2767 fail(e.getMessage());
2768 }
lucaslinf3b59b32019-03-26 17:49:49 +08002769 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002770 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
lucaslinf3b59b32019-03-26 17:49:49 +08002771 // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
2772 // NetworkMonitor detects partial connectivity
lucasline252a742019-03-12 13:08:03 +08002773 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002774 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2775 mWiFiNetworkAgent.setNetworkValid();
2776 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2777 // validated.
2778 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2779 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2780 mWiFiNetworkAgent.disconnect();
2781 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002782 }
2783
2784 @Test
Chiachang Wang8d573212019-05-23 22:57:18 -07002785 public void testCaptivePortalOnPartialConnectivity() throws RemoteException {
2786 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2787 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2788 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2789 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2790
2791 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2792 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2793 .addCapability(NET_CAPABILITY_VALIDATED).build();
2794 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2795
2796 // Bring up a network with a captive portal.
2797 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
2798 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Chiachang Wang6786252e2019-05-25 08:42:17 -07002799 String redirectUrl = "http://android.com/path";
2800 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
Chiachang Wang8d573212019-05-23 22:57:18 -07002801 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wang6786252e2019-05-25 08:42:17 -07002802 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8d573212019-05-23 22:57:18 -07002803
2804 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2805 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2806 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2807 .launchCaptivePortalApp();
2808
2809 // Report that the captive portal is dismissed with partial connectivity, and check that
2810 // callbacks are fired.
2811 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wang6786252e2019-05-25 08:42:17 -07002812 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8d573212019-05-23 22:57:18 -07002813 waitForIdle();
2814 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2815 mWiFiNetworkAgent);
2816
2817 // Report partial connectivity is accepted.
2818 mWiFiNetworkAgent.setNetworkPartialValid();
2819 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2820 false /* always */);
2821 waitForIdle();
2822 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang6786252e2019-05-25 08:42:17 -07002823 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chiachang Wang8d573212019-05-23 22:57:18 -07002824 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2825 NetworkCapabilities nc =
2826 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2827 mWiFiNetworkAgent);
2828
2829 mCm.unregisterNetworkCallback(captivePortalCallback);
2830 mCm.unregisterNetworkCallback(validatedCallback);
2831 }
2832
2833 @Test
Paul Jensencf4c2c62015-07-01 14:16:32 -04002834 public void testCaptivePortal() {
2835 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2836 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2837 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2838 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2839
2840 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2841 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2842 .addCapability(NET_CAPABILITY_VALIDATED).build();
2843 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002844
2845 // Bring up a network with a captive portal.
2846 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002847 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002848 String firstRedirectUrl = "http://example.com/firstPath";
2849 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002850 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002851 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002852
2853 // Take down network.
2854 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002855 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002856 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002857
2858 // Bring up a network with a captive portal.
2859 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002860 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002861 String secondRedirectUrl = "http://example.com/secondPath";
2862 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002863 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002864 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002865
2866 // Make captive portal disappear then revalidate.
2867 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002868 mWiFiNetworkAgent.setNetworkValid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002869 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002870 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002871
2872 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002873 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN45527792019-06-25 09:40:54 -07002874 // Expect no notification to be shown when captive portal disappears by itself
2875 verify(mNotificationManager, never()).notifyAsUser(
2876 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002877
2878 // Break network connectivity.
2879 // Expect NET_CAPABILITY_VALIDATED onLost callback.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002880 mWiFiNetworkAgent.setNetworkInvalid();
Paul Jensencf4c2c62015-07-01 14:16:32 -04002881 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09002882 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002883 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002884
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002885 @Test
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002886 public void testCaptivePortalApp() throws RemoteException {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002887 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2888 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2889 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2890 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2891
2892 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2893 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2894 .addCapability(NET_CAPABILITY_VALIDATED).build();
2895 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2896
2897 // Bring up wifi.
2898 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2899 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002900 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002901 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2902
2903 // Check that calling startCaptivePortalApp does nothing.
2904 final int fastTimeoutMs = 100;
2905 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN45527792019-06-25 09:40:54 -07002906 waitForIdle();
2907 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002908 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2909
2910 // Turn into a captive portal.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002911 mWiFiNetworkAgent.setNetworkPortal("http://example.com");
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002912 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002913 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002914 validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
2915
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002916 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002917 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN45527792019-06-25 09:40:54 -07002918 waitForIdle();
2919 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2920
2921 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2922 final Bundle testBundle = new Bundle();
2923 final String testKey = "testkey";
2924 final String testValue = "testvalue";
2925 testBundle.putString(testKey, testValue);
2926 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2927 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2928 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2929 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002930
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002931 // Report that the captive portal is dismissed, and check that callbacks are fired
2932 mWiFiNetworkAgent.setNetworkValid();
2933 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002934 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002935 captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN45527792019-06-25 09:40:54 -07002936 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2937 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002938
2939 mCm.unregisterNetworkCallback(validatedCallback);
2940 mCm.unregisterNetworkCallback(captivePortalCallback);
2941 }
2942
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002943 @Test
Calvin On1f64f3f2016-10-11 15:10:46 -07002944 public void testAvoidOrIgnoreCaptivePortals() {
2945 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2946 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2947 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2948 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2949
2950 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2951 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2952 .addCapability(NET_CAPABILITY_VALIDATED).build();
2953 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2954
2955 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2956 // Bring up a network with a captive portal.
2957 // Expect it to fail to connect and not result in any callbacks.
2958 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
2959 String firstRedirectUrl = "http://example.com/firstPath";
2960
2961 ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
2962 ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
2963 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
2964 waitFor(disconnectCv);
2965 waitFor(avoidCv);
2966
2967 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002968 }
2969
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002970 private NetworkRequest.Builder newWifiRequestBuilder() {
2971 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2972 }
2973
Etan Cohen836ad572018-12-30 17:59:59 -08002974 /**
2975 * Verify request matching behavior with network specifiers.
2976 *
2977 * Note: this test is somewhat problematic since it involves removing capabilities from
2978 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2979 * as a WTF bug in
2980 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2981 * does work.
2982 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002983 @Test
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002984 public void testNetworkSpecifier() {
Etan Cohen836ad572018-12-30 17:59:59 -08002985 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2986 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2987 Parcelable {
2988 @Override
2989 public boolean satisfiedBy(NetworkSpecifier other) {
2990 return true;
2991 }
2992
2993 @Override
2994 public int describeContents() {
2995 return 0;
2996 }
2997
2998 @Override
2999 public void writeToParcel(Parcel dest, int flags) {}
3000
3001 @Override
3002 public NetworkSpecifier redact() {
3003 return null;
3004 }
3005 }
3006
3007 // A network specifier that matches either another LocalNetworkSpecifier with the same
3008 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
3009 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3010 private String mString;
3011
3012 LocalStringNetworkSpecifier(String string) {
3013 mString = string;
3014 }
3015
3016 @Override
3017 public boolean satisfiedBy(NetworkSpecifier other) {
3018 if (other instanceof LocalStringNetworkSpecifier) {
3019 return TextUtils.equals(mString,
3020 ((LocalStringNetworkSpecifier) other).mString);
3021 }
3022 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
3023 return false;
3024 }
3025
3026 @Override
3027 public int describeContents() {
3028 return 0;
3029 }
3030 @Override
3031 public void writeToParcel(Parcel dest, int flags) {}
3032 }
3033
3034
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003035 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07003036 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003037 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07003038 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
3039 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08003040 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
3041 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07003042 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08003043 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003044
3045 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
3046 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
3047 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07003048 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003049 TestNetworkCallback cFoo = new TestNetworkCallback();
3050 TestNetworkCallback cBar = new TestNetworkCallback();
3051 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08003052 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003053
3054 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
3055 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
3056 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07003057 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003058 mCm.registerNetworkCallback(rFoo, cFoo);
3059 mCm.registerNetworkCallback(rBar, cBar);
3060
Etan Cohen836ad572018-12-30 17:59:59 -08003061 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
3062 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
3063
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003064 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3065 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003066 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3067 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3068 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3069 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003070 assertNoCallbacks(cFoo, cBar);
3071
Etan Cohen836ad572018-12-30 17:59:59 -08003072 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003073 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003074 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08003075 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
3076 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003077 }
Etan Cohen836ad572018-12-30 17:59:59 -08003078 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
3079 mWiFiNetworkAgent);
3080 assertEquals(nsFoo,
3081 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003082 cFoo.assertNoCallback();
3083
Etan Cohen836ad572018-12-30 17:59:59 -08003084 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003085 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003086 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003087 for (TestNetworkCallback c: emptyCallbacks) {
Etan Cohen836ad572018-12-30 17:59:59 -08003088 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
3089 mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003090 }
Etan Cohen836ad572018-12-30 17:59:59 -08003091 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
3092 mWiFiNetworkAgent);
3093 assertEquals(nsBar,
3094 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3095 cBar.assertNoCallback();
3096
3097 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
3098 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3099 for (TestNetworkCallback c : emptyCallbacks) {
3100 c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3101 mWiFiNetworkAgent);
3102 }
3103 cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3104 mWiFiNetworkAgent);
3105 cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
3106 mWiFiNetworkAgent);
3107 assertNull(
3108 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3109 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003110 cBar.assertNoCallback();
3111
3112 mWiFiNetworkAgent.setNetworkSpecifier(null);
Etan Cohen836ad572018-12-30 17:59:59 -08003113 cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003114 cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3115 for (TestNetworkCallback c: emptyCallbacks) {
3116 c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
3117 }
3118
Etan Cohen836ad572018-12-30 17:59:59 -08003119 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003120 }
3121
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003122 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08003123 public void testInvalidNetworkSpecifier() {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003124 try {
3125 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07003126 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
3127 fail("NetworkRequest builder with MatchAllNetworkSpecifier");
3128 } catch (IllegalArgumentException expected) {
3129 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08003130 }
3131
Etan Cohenddb9ef02015-11-18 10:56:15 -08003132 try {
3133 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3134 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07003135 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08003136 mService.requestNetwork(networkCapabilities, null, 0, null,
3137 ConnectivityManager.TYPE_WIFI);
Etan Cohena7434272017-04-03 12:17:51 -07003138 fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
3139 } catch (IllegalArgumentException expected) {
3140 // expected
Etan Cohenddb9ef02015-11-18 10:56:15 -08003141 }
3142
Etan Cohena7434272017-04-03 12:17:51 -07003143 class NonParcelableSpecifier extends NetworkSpecifier {
3144 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
3145 };
3146 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3147 @Override public int describeContents() { return 0; }
3148 @Override public void writeToParcel(Parcel p, int flags) {}
3149 }
3150 NetworkRequest.Builder builder;
3151
3152 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3153 try {
3154 builder.setNetworkSpecifier(new NonParcelableSpecifier());
3155 Parcel parcelW = Parcel.obtain();
3156 builder.build().writeToParcel(parcelW, 0);
3157 fail("Parceling a non-parcelable specifier did not throw an exception");
3158 } catch (Exception e) {
3159 // expected
3160 }
3161
3162 builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3163 builder.setNetworkSpecifier(new ParcelableSpecifier());
3164 NetworkRequest nr = builder.build();
3165 assertNotNull(nr);
3166
3167 try {
3168 Parcel parcelW = Parcel.obtain();
3169 nr.writeToParcel(parcelW, 0);
3170 byte[] bytes = parcelW.marshall();
3171 parcelW.recycle();
3172
3173 Parcel parcelR = Parcel.obtain();
3174 parcelR.unmarshall(bytes, 0, bytes.length);
3175 parcelR.setDataPosition(0);
3176 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
3177 fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
3178 } catch (Exception e) {
3179 // expected
3180 }
Etan Cohenddb9ef02015-11-18 10:56:15 -08003181 }
3182
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003183 @Test
Etan Cohen859748f2017-04-03 17:42:34 -07003184 public void testNetworkSpecifierUidSpoofSecurityException() {
3185 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3186 @Override
3187 public boolean satisfiedBy(NetworkSpecifier other) {
3188 return true;
3189 }
3190
3191 @Override
3192 public void assertValidFromUid(int requestorUid) {
3193 throw new SecurityException("failure");
3194 }
3195
3196 @Override
3197 public int describeContents() { return 0; }
3198 @Override
3199 public void writeToParcel(Parcel dest, int flags) {}
3200 }
3201
3202 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3203 mWiFiNetworkAgent.connect(false);
3204
3205 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
3206 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
3207 networkSpecifier).build();
3208 TestNetworkCallback networkCallback = new TestNetworkCallback();
3209 try {
3210 mCm.requestNetwork(networkRequest, networkCallback);
3211 fail("Network request with spoofed UID did not throw a SecurityException");
3212 } catch (SecurityException e) {
3213 // expected
3214 }
3215 }
3216
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003217 @Test
paulhu3d67f532019-03-22 16:35:06 +08003218 public void testInvalidSignalStrength() {
3219 NetworkRequest r = new NetworkRequest.Builder()
3220 .addCapability(NET_CAPABILITY_INTERNET)
3221 .addTransportType(TRANSPORT_WIFI)
3222 .setSignalStrength(-75)
3223 .build();
3224 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3225 // permission should get SecurityException.
3226 try {
3227 mCm.registerNetworkCallback(r, new NetworkCallback());
3228 fail("Expected SecurityException filing a callback with signal strength");
3229 } catch (SecurityException expected) {
3230 // expected
3231 }
3232
3233 try {
3234 mCm.registerNetworkCallback(r, PendingIntent.getService(
3235 mServiceContext, 0, new Intent(), 0));
3236 fail("Expected SecurityException filing a callback with signal strength");
3237 } catch (SecurityException expected) {
3238 // expected
3239 }
3240
3241 // Requesting a Network with signal strength should get IllegalArgumentException.
3242 try {
3243 mCm.requestNetwork(r, new NetworkCallback());
3244 fail("Expected IllegalArgumentException filing a request with signal strength");
3245 } catch (IllegalArgumentException expected) {
3246 // expected
3247 }
3248
3249 try {
3250 mCm.requestNetwork(r, PendingIntent.getService(
3251 mServiceContext, 0, new Intent(), 0));
3252 fail("Expected IllegalArgumentException filing a request with signal strength");
3253 } catch (IllegalArgumentException expected) {
3254 // expected
3255 }
3256 }
3257
3258 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003259 public void testRegisterDefaultNetworkCallback() throws Exception {
3260 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3261 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3262 defaultNetworkCallback.assertNoCallback();
3263
3264 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3265 // whenever Wi-Fi is up. Without this, the mobile network agent is
3266 // reaped before any other activity can take place.
3267 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3268 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3269 .addTransportType(TRANSPORT_CELLULAR).build();
3270 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3271 cellNetworkCallback.assertNoCallback();
3272
3273 // Bring up cell and expect CALLBACK_AVAILABLE.
3274 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3275 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003276 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3277 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003278 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003279
3280 // Bring up wifi and expect CALLBACK_AVAILABLE.
3281 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3282 mWiFiNetworkAgent.connect(true);
3283 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003284 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003285 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003286
3287 // Bring down cell. Expect no default network callback, since it wasn't the default.
3288 mCellNetworkAgent.disconnect();
3289 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3290 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003291 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003292
3293 // Bring up cell. Expect no default network callback, since it won't be the default.
3294 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3295 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003296 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003297 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003298 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003299
3300 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3301 // followed by AVAILABLE cell.
3302 mWiFiNetworkAgent.disconnect();
3303 cellNetworkCallback.assertNoCallback();
3304 defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003305 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003306 mCellNetworkAgent.disconnect();
3307 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
3308 defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003309 waitForIdle();
3310 assertEquals(null, mCm.getActiveNetwork());
3311
3312 final int uid = Process.myUid();
3313 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
3314 final ArraySet<UidRange> ranges = new ArraySet<>();
3315 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003316 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3317 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003318 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003319 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003320 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3321 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3322
3323 vpnNetworkAgent.disconnect();
3324 defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
3325 waitForIdle();
3326 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003327 }
3328
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003329 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003330 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003331 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003332 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003333 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3334 .addTransportType(TRANSPORT_CELLULAR).build();
3335 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3336
3337 // Bring up the mobile network.
3338 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3339 mCellNetworkAgent.connect(true);
3340
Erik Kline1d3db322017-02-28 16:20:20 +09003341 // We should get onAvailable(), onCapabilitiesChanged(), and
3342 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3343 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003344 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003345 cellNetworkCallback.assertNoCallback();
3346
3347 // Update LinkProperties.
3348 final LinkProperties lp = new LinkProperties();
3349 lp.setInterfaceName("foonet_data0");
3350 mCellNetworkAgent.sendLinkProperties(lp);
3351 // We should get onLinkPropertiesChanged().
3352 cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
3353 cellNetworkCallback.assertNoCallback();
3354
Erik Kline1d3db322017-02-28 16:20:20 +09003355 // Suspend the network.
3356 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003357 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3358 mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003359 cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
3360 cellNetworkCallback.assertNoCallback();
3361
Erik Klineacdd6392016-07-07 16:50:58 +09003362 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003363 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003364 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003365 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3366 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003367 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003368 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003369 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3370
3371 mCellNetworkAgent.resume();
3372 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3373 mCellNetworkAgent);
3374 cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
3375 cellNetworkCallback.assertNoCallback();
3376
3377 dfltNetworkCallback = new TestNetworkCallback();
3378 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3379 // This time onNetworkSuspended should not be called.
3380 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3381 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003382
Erik Klineacdd6392016-07-07 16:50:58 +09003383 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3384 mCm.unregisterNetworkCallback(cellNetworkCallback);
3385 }
3386
Calvin On1f64f3f2016-10-11 15:10:46 -07003387 private void setCaptivePortalMode(int mode) {
3388 ContentResolver cr = mServiceContext.getContentResolver();
3389 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3390 }
3391
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003392 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003393 ContentResolver cr = mServiceContext.getContentResolver();
3394 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003395 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003396 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003397 }
3398
Erik Kline79c6d052018-03-21 07:18:33 -07003399 private void setPrivateDnsSettings(String mode, String specifier) {
3400 final ContentResolver cr = mServiceContext.getContentResolver();
3401 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3402 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3403 mService.updatePrivateDnsSettings();
3404 waitForIdle();
3405 }
3406
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003407 private boolean isForegroundNetwork(MockNetworkAgent network) {
3408 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3409 assertNotNull(nc);
3410 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3411 }
3412
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003413 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003414 public void testBackgroundNetworks() throws Exception {
3415 // Create a background request. We can't do this ourselves because ConnectivityService
3416 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003417 setAlwaysOnNetworks(true);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003418 final NetworkRequest request = new NetworkRequest.Builder().build();
3419 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3420 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3421 final TestNetworkCallback callback = new TestNetworkCallback();
3422 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3423 mCm.registerNetworkCallback(request, callback);
3424 mCm.registerNetworkCallback(fgRequest, fgCallback);
3425
3426 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3427 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003428 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3429 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003430 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3431
3432 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3433 mWiFiNetworkAgent.connect(true);
3434
3435 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003436 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003437 callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003438 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003439 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003440 fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003441 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003442 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3443 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3444
3445 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003446 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003447 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
3448 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003449 // Expect a network capabilities update sans FOREGROUND.
3450 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003451 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3452 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3453
3454 // File a cell request and check that cell comes into the foreground.
3455 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3456 .addTransportType(TRANSPORT_CELLULAR).build();
3457 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3458 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003459 // NOTE: This request causes the network's capabilities to change. This
3460 // is currently delivered before the onAvailable() callbacks.
3461 // TODO: Fix this.
3462 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003463 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3464 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003465 // Expect a network capabilities update with FOREGROUND, because the most recent
3466 // request causes its state to change.
3467 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003468 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3469 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3470
3471 // Release the request. The network immediately goes into the background, since it was not
3472 // lingering.
3473 mCm.unregisterNetworkCallback(cellCallback);
3474 fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003475 // Expect a network capabilities update sans FOREGROUND.
3476 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003477 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3478 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3479
3480 // Disconnect wifi and check that cell is foreground again.
3481 mWiFiNetworkAgent.disconnect();
3482 callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3483 fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003484 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003485 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3486
3487 mCm.unregisterNetworkCallback(callback);
3488 mCm.unregisterNetworkCallback(fgCallback);
3489 }
3490
Hugo Benichi849b81b2017-05-25 13:42:31 +09003491 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003492 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003493 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003494 // Benchmarks connecting and switching performance in the presence of a large number of
3495 // NetworkRequests.
3496 // 1. File NUM_REQUESTS requests.
3497 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3498 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3499 // and NUM_REQUESTS onAvailable callbacks to fire.
3500 // See how long it took.
3501 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003502 final int REGISTER_TIME_LIMIT_MS = 200;
3503 final int CONNECT_TIME_LIMIT_MS = 60;
3504 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003505 final int UNREGISTER_TIME_LIMIT_MS = 20;
3506
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003507 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3508 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3509 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3510 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3511
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003512 for (int i = 0; i < NUM_REQUESTS; i++) {
3513 callbacks[i] = new NetworkCallback() {
3514 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3515 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3516 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003517 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003518
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003519 assertTimeLimit("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
3520 for (NetworkCallback cb : callbacks) {
3521 mCm.registerNetworkCallback(request, cb);
3522 }
3523 });
3524
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003525 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3526 // Don't request that the network validate, because otherwise connect() will block until
3527 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3528 // and we won't actually measure anything.
3529 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003530
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003531 long onAvailableDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003532 awaitLatch(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003533 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003534 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3535 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3536 onAvailableDispatchingDuration));
3537 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3538 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3539 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003540
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003541 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003542 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003543 mWiFiNetworkAgent.adjustScore(40);
3544 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003545
3546 long onLostDispatchingDuration = durationOf(() -> {
Hugo Benichibb91c572017-05-22 10:44:02 +09003547 awaitLatch(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003548 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003549 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3550 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3551 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3552 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3553 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003554
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003555 assertTimeLimit("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
3556 for (NetworkCallback cb : callbacks) {
3557 mCm.unregisterNetworkCallback(cb);
3558 }
3559 });
3560 }
3561
3562 private long durationOf(Runnable fn) {
3563 long startTime = SystemClock.elapsedRealtime();
3564 fn.run();
3565 return SystemClock.elapsedRealtime() - startTime;
3566 }
3567
3568 private void assertTimeLimit(String descr, long timeLimit, Runnable fn) {
3569 long timeTaken = durationOf(fn);
3570 String msg = String.format("%s: took %dms, limit was %dms", descr, timeTaken, timeLimit);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003571 Log.d(TAG, msg);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003572 assertTrue(msg, timeTaken <= timeLimit);
3573 }
3574
3575 private boolean awaitLatch(CountDownLatch l, long timeoutMs) {
3576 try {
Hugo Benichibb91c572017-05-22 10:44:02 +09003577 return l.await(timeoutMs, TimeUnit.MILLISECONDS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003578 } catch (InterruptedException e) {}
3579 return false;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003580 }
3581
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003582 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003583 public void testMobileDataAlwaysOn() throws Exception {
3584 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3585 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3586 .addTransportType(TRANSPORT_CELLULAR).build();
3587 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3588
3589 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3590 handlerThread.start();
3591 NetworkCapabilities filter = new NetworkCapabilities()
3592 .addTransportType(TRANSPORT_CELLULAR)
3593 .addCapability(NET_CAPABILITY_INTERNET);
3594 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3595 mServiceContext, "testFactory", filter);
3596 testFactory.setScoreFilter(40);
3597
3598 // Register the factory and expect it to start looking for a network.
Chalard Jean08577fc2018-05-02 21:14:54 +09003599 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003600 testFactory.register();
3601 testFactory.waitForNetworkRequests(1);
3602 assertTrue(testFactory.getMyStartRequested());
3603
3604 // Bring up wifi. The factory stops looking for a network.
3605 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
Chalard Jean08577fc2018-05-02 21:14:54 +09003606 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3607 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003608 mWiFiNetworkAgent.connect(true);
Chalard Jean08577fc2018-05-02 21:14:54 +09003609 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003610 assertFalse(testFactory.getMyStartRequested());
3611
3612 ContentResolver cr = mServiceContext.getContentResolver();
3613
3614 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean08577fc2018-05-02 21:14:54 +09003615 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003616 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003617 testFactory.waitForNetworkRequests(2);
3618 assertTrue(testFactory.getMyStartRequested());
3619
3620 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003621 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003622 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Chalard Jean08577fc2018-05-02 21:14:54 +09003623 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003624 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003625 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003626 testFactory.waitForNetworkRequests(2);
3627 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3628
3629 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003630 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003631 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003632 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003633
3634 // Turn off mobile data always on and expect the request to disappear...
3635 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003636 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003637 testFactory.waitForNetworkRequests(1);
3638
3639 // ... and cell data to be torn down.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003640 cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003641 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003642
3643 testFactory.unregister();
3644 mCm.unregisterNetworkCallback(cellNetworkCallback);
3645 handlerThread.quit();
3646 }
3647
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003648 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003649 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003650 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003651 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003652 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3653
Erik Kline065ab6e2016-10-02 18:02:14 +09003654 tracker.configRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003655 String[] values = new String[] {null, "0", "1"};
3656 for (int i = 0; i < values.length; i++) {
3657 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003658 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003659 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003660 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003661 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003662 assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003663 }
3664
Erik Kline065ab6e2016-10-02 18:02:14 +09003665 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003666
3667 Settings.Global.putInt(cr, settingName, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003668 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003669 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003670 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003671 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003672
3673 Settings.Global.putInt(cr, settingName, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003674 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003675 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003676 assertTrue(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003677 assertFalse(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003678
3679 Settings.Global.putString(cr, settingName, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003680 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003681 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003682 assertFalse(mService.avoidBadWifi());
Erik Kline065ab6e2016-10-02 18:02:14 +09003683 assertTrue(tracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003684 }
3685
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003686 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003687 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003688 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +09003689 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003690
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003691 // Pretend we're on a carrier that restricts switching away from bad wifi.
Erik Kline065ab6e2016-10-02 18:02:14 +09003692 tracker.configRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003693
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003694 // File a request for cell to ensure it doesn't go down.
3695 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3696 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3697 .addTransportType(TRANSPORT_CELLULAR).build();
3698 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3699
3700 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3701 mCm.registerDefaultNetworkCallback(defaultCallback);
3702
3703 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3704 .addTransportType(TRANSPORT_WIFI)
3705 .addCapability(NET_CAPABILITY_VALIDATED)
3706 .build();
3707 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3708 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3709
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003710 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Erik Kline065ab6e2016-10-02 18:02:14 +09003711 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003712
3713 // Bring up validated cell.
3714 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
3715 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003716 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3717 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003718 Network cellNetwork = mCellNetworkAgent.getNetwork();
3719
3720 // Bring up validated wifi.
3721 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3722 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003723 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3724 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003725 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3726
3727 // Fail validation on wifi.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003728 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003729 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003730 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003731 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3732
3733 // Because avoid bad wifi is off, we don't switch to cellular.
3734 defaultCallback.assertNoCallback();
3735 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3736 NET_CAPABILITY_VALIDATED));
3737 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3738 NET_CAPABILITY_VALIDATED));
3739 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3740
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003741 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3742 // that we switch back to cell.
Erik Kline065ab6e2016-10-02 18:02:14 +09003743 tracker.configRestrictsAvoidBadWifi = false;
3744 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003745 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003746 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3747
3748 // Switch back to a restrictive carrier.
Erik Kline065ab6e2016-10-02 18:02:14 +09003749 tracker.configRestrictsAvoidBadWifi = true;
3750 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003751 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003752 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3753
3754 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3755 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003756 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003757 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3758 NET_CAPABILITY_VALIDATED));
3759 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3760 NET_CAPABILITY_VALIDATED));
3761 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3762
3763 // Disconnect and reconnect wifi to clear the one-time switch above.
3764 mWiFiNetworkAgent.disconnect();
3765 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3766 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003767 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3768 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003769 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3770
3771 // Fail validation on wifi and expect the dialog to appear.
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09003772 mWiFiNetworkAgent.setNetworkInvalid();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003773 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003774 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003775 validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3776
3777 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003778 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003779 tracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003780
3781 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003782 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003783 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3784 NET_CAPABILITY_VALIDATED));
3785 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3786 NET_CAPABILITY_VALIDATED));
3787 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3788
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003789 // Simulate the user turning the cellular fallback setting off and then on.
3790 // We switch to wifi and then to cell.
3791 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Erik Kline065ab6e2016-10-02 18:02:14 +09003792 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003793 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003794 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3795 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Erik Kline065ab6e2016-10-02 18:02:14 +09003796 tracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003797 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003798 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3799
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003800 // If cell goes down, we switch to wifi.
3801 mCellNetworkAgent.disconnect();
3802 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003803 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003804 validatedWifiCallback.assertNoCallback();
3805
3806 mCm.unregisterNetworkCallback(cellNetworkCallback);
3807 mCm.unregisterNetworkCallback(validatedWifiCallback);
3808 mCm.unregisterNetworkCallback(defaultCallback);
3809 }
3810
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003811 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003812 public void testMeteredMultipathPreferenceSetting() throws Exception {
3813 final ContentResolver cr = mServiceContext.getContentResolver();
3814 final WrappedMultinetworkPolicyTracker tracker = mService.getMultinetworkPolicyTracker();
3815 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3816
3817 for (int config : Arrays.asList(0, 3, 2)) {
3818 for (String setting: Arrays.asList(null, "0", "2", "1")) {
3819 tracker.configMeteredMultipathPreference = config;
3820 Settings.Global.putString(cr, settingName, setting);
3821 tracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003822 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003823
3824 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3825 String msg = String.format("config=%d, setting=%s", config, setting);
3826 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3827 }
3828 }
3829 }
3830
Erik Kline3841a482015-11-25 12:49:38 +09003831 /**
3832 * Validate that a satisfied network request does not trigger onUnavailable() once the
3833 * time-out period expires.
3834 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003835 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003836 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
3837 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3838 NetworkCapabilities.TRANSPORT_WIFI).build();
3839 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003840 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003841
3842 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3843 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003844 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003845 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003846
3847 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003848 networkCallback.assertNoCallback();
3849 }
3850
3851 /**
3852 * Validate that a satisfied network request followed by a disconnected (lost) network does
3853 * not trigger onUnavailable() once the time-out period expires.
3854 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003855 @Test
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003856 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
3857 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3858 NetworkCapabilities.TRANSPORT_WIFI).build();
3859 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003860 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003861
3862 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3863 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003864 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003865 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003866 mWiFiNetworkAgent.disconnect();
3867 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
3868
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003869 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003870 networkCallback.assertNoCallback();
3871 }
3872
3873 /**
3874 * Validate that when a time-out is specified for a network request the onUnavailable()
3875 * callback is called when time-out expires. Then validate that if network request is
3876 * (somehow) satisfied - the callback isn't called later.
3877 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003878 @Test
Erik Kline3841a482015-11-25 12:49:38 +09003879 public void testTimedoutNetworkRequest() {
3880 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3881 NetworkCapabilities.TRANSPORT_WIFI).build();
3882 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003883 final int timeoutMs = 10;
3884 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003885
3886 // pass timeout and validate that UNAVAILABLE is called
3887 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3888
3889 // create a network satisfying request - validate that request not triggered
3890 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3891 mWiFiNetworkAgent.connect(false);
3892 networkCallback.assertNoCallback();
3893 }
3894
3895 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003896 * Validate that when a network request is unregistered (cancelled), no posterior event can
3897 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003898 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003899 @Test
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003900 public void testNoCallbackAfterUnregisteredNetworkRequest() {
Erik Kline3841a482015-11-25 12:49:38 +09003901 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3902 NetworkCapabilities.TRANSPORT_WIFI).build();
3903 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003904 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003905
Hugo Benichidfb559a2016-12-20 14:57:49 +09003906 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003907 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003908 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3909 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003910 networkCallback.assertNoCallback();
3911
3912 // create a network satisfying request - validate that request not triggered
3913 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
3914 mWiFiNetworkAgent.connect(false);
3915 networkCallback.assertNoCallback();
3916 }
3917
Etan Cohen46c23572019-05-22 09:17:33 -07003918 @Test
3919 public void testUnfulfillableNetworkRequest() throws Exception {
3920 runUnfulfillableNetworkRequest(false);
3921 }
3922
3923 @Test
3924 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3925 runUnfulfillableNetworkRequest(true);
3926 }
3927
Etan Cohenae574a82019-01-08 12:09:18 -08003928 /**
3929 * Validate the callback flow for a factory releasing a request as unfulfillable.
3930 */
Etan Cohen46c23572019-05-22 09:17:33 -07003931 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenae574a82019-01-08 12:09:18 -08003932 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3933 NetworkCapabilities.TRANSPORT_WIFI).build();
3934 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3935
3936 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3937 handlerThread.start();
3938 NetworkCapabilities filter = new NetworkCapabilities()
3939 .addTransportType(TRANSPORT_WIFI)
3940 .addCapability(NET_CAPABILITY_INTERNET);
3941 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3942 mServiceContext, "testFactory", filter);
3943 testFactory.setScoreFilter(40);
3944
3945 // Register the factory and expect it to receive the default request.
3946 testFactory.expectAddRequestsWithScores(0);
3947 testFactory.register();
3948 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3949
3950 assertEquals(1, requests.size()); // have 1 request at this point
3951 int origRequestId = requests.valueAt(0).requestId;
3952
3953 // Now file the test request and expect it.
3954 testFactory.expectAddRequestsWithScores(0);
3955 mCm.requestNetwork(nr, networkCallback);
3956 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3957
3958 int newRequestId = 0;
3959 for (int i = 0; i < requests.size(); ++i) {
3960 if (requests.valueAt(i).requestId != origRequestId) {
3961 newRequestId = requests.valueAt(i).requestId;
3962 break;
3963 }
3964 }
3965
Etan Cohen9869b472019-05-23 09:16:26 -07003966 testFactory.expectRemoveRequests(1);
Etan Cohen46c23572019-05-22 09:17:33 -07003967 if (preUnregister) {
3968 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenae574a82019-01-08 12:09:18 -08003969
Etan Cohen46c23572019-05-22 09:17:33 -07003970 // Simulate the factory releasing the request as unfulfillable: no-op since
3971 // the callback has already been unregistered (but a test that no exceptions are
3972 // thrown).
3973 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3974 } else {
3975 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen46c23572019-05-22 09:17:33 -07003976 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3977
3978 networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
3979 testFactory.waitForRequests();
3980
3981 // unregister network callback - a no-op (since already freed by the
3982 // on-unavailable), but should not fail or throw exceptions.
3983 mCm.unregisterNetworkCallback(networkCallback);
3984 }
Etan Cohen5acedec2019-04-16 15:07:55 -07003985
Etan Cohenae574a82019-01-08 12:09:18 -08003986 testFactory.unregister();
3987 handlerThread.quit();
3988 }
3989
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003990 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3991
3992 public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3993
3994 private class CallbackValue {
3995 public CallbackType callbackType;
3996 public int error;
3997
3998 public CallbackValue(CallbackType type) {
3999 this.callbackType = type;
4000 this.error = PacketKeepalive.SUCCESS;
4001 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
4002 }
4003
4004 public CallbackValue(CallbackType type, int error) {
4005 this.callbackType = type;
4006 this.error = error;
4007 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
4008 }
4009
4010 @Override
4011 public boolean equals(Object o) {
4012 return o instanceof CallbackValue &&
4013 this.callbackType == ((CallbackValue) o).callbackType &&
4014 this.error == ((CallbackValue) o).error;
4015 }
4016
4017 @Override
4018 public String toString() {
4019 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
4020 }
4021 }
4022
junyulai7c469172019-01-16 20:23:34 +08004023 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004024
4025 @Override
4026 public void onStarted() {
4027 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
4028 }
4029
4030 @Override
4031 public void onStopped() {
4032 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
4033 }
4034
4035 @Override
4036 public void onError(int error) {
4037 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
4038 }
4039
4040 private void expectCallback(CallbackValue callbackValue) {
4041 try {
4042 assertEquals(
4043 callbackValue,
4044 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4045 } catch (InterruptedException e) {
4046 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
4047 }
4048 }
4049
4050 public void expectStarted() {
4051 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4052 }
4053
4054 public void expectStopped() {
4055 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4056 }
4057
4058 public void expectError(int error) {
4059 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4060 }
4061 }
4062
junyulai48eac1d42018-12-27 17:25:29 +08004063 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
4064
4065 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
4066
4067 private class CallbackValue {
4068 public CallbackType callbackType;
4069 public int error;
4070
4071 CallbackValue(CallbackType type) {
4072 this.callbackType = type;
4073 this.error = SocketKeepalive.SUCCESS;
4074 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
4075 }
4076
4077 CallbackValue(CallbackType type, int error) {
4078 this.callbackType = type;
4079 this.error = error;
4080 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
4081 }
4082
4083 @Override
4084 public boolean equals(Object o) {
4085 return o instanceof CallbackValue
4086 && this.callbackType == ((CallbackValue) o).callbackType
4087 && this.error == ((CallbackValue) o).error;
4088 }
4089
4090 @Override
4091 public String toString() {
4092 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
4093 error);
4094 }
4095 }
4096
4097 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08004098 private final Executor mExecutor;
4099
4100 TestSocketKeepaliveCallback(@NonNull Executor executor) {
4101 mExecutor = executor;
4102 }
junyulai48eac1d42018-12-27 17:25:29 +08004103
4104 @Override
4105 public void onStarted() {
4106 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
4107 }
4108
4109 @Override
4110 public void onStopped() {
4111 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
4112 }
4113
4114 @Override
4115 public void onError(int error) {
4116 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
4117 }
4118
4119 private void expectCallback(CallbackValue callbackValue) {
4120 try {
4121 assertEquals(
4122 callbackValue,
4123 mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4124 } catch (InterruptedException e) {
4125 fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
4126 }
4127 }
4128
4129 public void expectStarted() {
4130 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4131 }
4132
4133 public void expectStopped() {
4134 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4135 }
4136
4137 public void expectError(int error) {
4138 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4139 }
junyulai7c469172019-01-16 20:23:34 +08004140
4141 public void assertNoCallback() {
4142 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
4143 CallbackValue cv = mCallbacks.peek();
4144 assertNull("Unexpected callback: " + cv, cv);
4145 }
junyulai48eac1d42018-12-27 17:25:29 +08004146 }
4147
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004148 private Network connectKeepaliveNetwork(LinkProperties lp) {
4149 // Ensure the network is disconnected before we do anything.
4150 if (mWiFiNetworkAgent != null) {
4151 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
4152 }
4153
4154 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4155 ConditionVariable cv = waitForConnectivityBroadcasts(1);
4156 mWiFiNetworkAgent.connect(true);
4157 waitFor(cv);
4158 verifyActiveNetwork(TRANSPORT_WIFI);
4159 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09004160 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004161 return mWiFiNetworkAgent.getNetwork();
4162 }
4163
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004164 @Test
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004165 public void testPacketKeepalives() throws Exception {
4166 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4167 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4168 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4169 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4170 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4171
Nathan Harold63dd8132018-02-14 13:09:45 -08004172 final int validKaInterval = 15;
4173 final int invalidKaInterval = 9;
4174
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004175 LinkProperties lp = new LinkProperties();
4176 lp.setInterfaceName("wlan12");
4177 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4178 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4179 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4180 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4181
4182 Network notMyNet = new Network(61234);
4183 Network myNet = connectKeepaliveNetwork(lp);
4184
4185 TestKeepaliveCallback callback = new TestKeepaliveCallback();
4186 PacketKeepalive ka;
4187
4188 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08004189 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004190 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4191
Nathan Harold63dd8132018-02-14 13:09:45 -08004192 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004193 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4194
Nathan Harold63dd8132018-02-14 13:09:45 -08004195 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004196 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4197
Nathan Harold63dd8132018-02-14 13:09:45 -08004198 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004199 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4200
Nathan Harold63dd8132018-02-14 13:09:45 -08004201 // NAT-T is only supported for IPv4.
4202 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4203 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004204
Nathan Harold63dd8132018-02-14 13:09:45 -08004205 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004206 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4207
Nathan Harold63dd8132018-02-14 13:09:45 -08004208 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004209 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4210
Nathan Harold63dd8132018-02-14 13:09:45 -08004211 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004212 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4213
Nathan Harold63dd8132018-02-14 13:09:45 -08004214 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004215 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4216
4217 // Check that a started keepalive can be stopped.
4218 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08004219 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004220 callback.expectStarted();
4221 mWiFiNetworkAgent.setStopKeepaliveError(PacketKeepalive.SUCCESS);
4222 ka.stop();
4223 callback.expectStopped();
4224
4225 // Check that deleting the IP address stops the keepalive.
4226 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08004227 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004228 callback.expectStarted();
4229 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4230 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4231 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4232 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4233 mWiFiNetworkAgent.sendLinkProperties(lp);
4234
4235 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004236 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004237 callback.expectStarted();
4238 mWiFiNetworkAgent.disconnect();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004239 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004240 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4241
4242 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004243 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004244 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004245 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004246 ka.stop();
4247
4248 // Reconnect.
4249 myNet = connectKeepaliveNetwork(lp);
4250 mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
4251
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004252 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4253 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004254 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004255 callback.expectStarted();
4256
4257 // The second one gets slot 2.
4258 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4259 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004260 PacketKeepalive ka2 = mCm.startNattKeepalive(
4261 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004262 callback2.expectStarted();
4263
4264 // Now stop the first one and create a third. This also gets slot 1.
4265 ka.stop();
4266 callback.expectStopped();
4267
4268 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4269 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004270 PacketKeepalive ka3 = mCm.startNattKeepalive(
4271 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004272 callback3.expectStarted();
4273
4274 ka2.stop();
4275 callback2.expectStopped();
4276
4277 ka3.stop();
4278 callback3.expectStopped();
4279 }
Udam Sainib7c24872016-01-04 12:16:14 -08004280
junyulaiafe9b492019-03-19 18:50:23 +08004281 @FunctionalInterface
4282 private interface ThrowingConsumer<T> {
4283 void accept(T t) throws Exception;
4284 }
4285
Xiao Maa4637112019-02-07 15:03:57 +09004286 // Helper method to prepare the executor and run test
junyulaiafe9b492019-03-19 18:50:23 +08004287 private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
junyulaie4135282019-01-03 18:50:15 +08004288 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004289 final Executor executorInline = (Runnable r) -> r.run();
4290 functor.accept(executorSingleThread);
junyulaie4135282019-01-03 18:50:15 +08004291 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004292 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004293 }
junyulaie4135282019-01-03 18:50:15 +08004294
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004295 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004296 public void testNattSocketKeepalives() throws Exception {
4297 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4298 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulaie4135282019-01-03 18:50:15 +08004299 }
4300
4301 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004302 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulaie4135282019-01-03 18:50:15 +08004303 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004304 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004305 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4306 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4307 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4308 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4309 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4310
4311 final int validKaInterval = 15;
4312 final int invalidKaInterval = 9;
4313
4314 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004315 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4316 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004317
junyulai48eac1d42018-12-27 17:25:29 +08004318 LinkProperties lp = new LinkProperties();
4319 lp.setInterfaceName("wlan12");
4320 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4321 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4322 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4323 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4324
4325 Network notMyNet = new Network(61234);
4326 Network myNet = connectKeepaliveNetwork(lp);
4327
junyulai7c469172019-01-16 20:23:34 +08004328 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004329
4330 // Attempt to start keepalives with invalid parameters and check for errors.
4331 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004332 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4333 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4334 ka.start(validKaInterval);
4335 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4336 }
junyulai48eac1d42018-12-27 17:25:29 +08004337
4338 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004339 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4340 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4341 ka.start(invalidKaInterval);
4342 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4343 }
junyulai48eac1d42018-12-27 17:25:29 +08004344
4345 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004346 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4347 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4348 ka.start(validKaInterval);
4349 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4350 }
junyulai48eac1d42018-12-27 17:25:29 +08004351
4352 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004353 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4354 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4355 ka.start(validKaInterval);
4356 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4357 }
junyulai48eac1d42018-12-27 17:25:29 +08004358
4359 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004360 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4361 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4362 ka.start(validKaInterval);
4363 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4364 }
junyulai48eac1d42018-12-27 17:25:29 +08004365
4366 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004367 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4368 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4369 ka.start(validKaInterval);
4370 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4371 }
junyulai48eac1d42018-12-27 17:25:29 +08004372
4373 // Check that a started keepalive can be stopped.
4374 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004375 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4376 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4377 ka.start(validKaInterval);
4378 callback.expectStarted();
4379 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4380 ka.stop();
4381 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004382
junyulai0c666972019-03-04 22:45:36 +08004383 // Check that keepalive could be restarted.
4384 ka.start(validKaInterval);
4385 callback.expectStarted();
4386 ka.stop();
4387 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004388
junyulai0c666972019-03-04 22:45:36 +08004389 // Check that keepalive can be restarted without waiting for callback.
4390 ka.start(validKaInterval);
4391 callback.expectStarted();
4392 ka.stop();
4393 ka.start(validKaInterval);
4394 callback.expectStopped();
4395 callback.expectStarted();
4396 ka.stop();
4397 callback.expectStopped();
4398 }
junyulai7c469172019-01-16 20:23:34 +08004399
junyulai48eac1d42018-12-27 17:25:29 +08004400 // Check that deleting the IP address stops the keepalive.
4401 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004402 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4403 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4404 ka.start(validKaInterval);
4405 callback.expectStarted();
4406 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4407 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4408 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4409 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4410 mWiFiNetworkAgent.sendLinkProperties(lp);
4411 }
junyulai48eac1d42018-12-27 17:25:29 +08004412
4413 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004414 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4415 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4416 ka.start(validKaInterval);
4417 callback.expectStarted();
4418 mWiFiNetworkAgent.disconnect();
4419 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4420 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004421
junyulai0c666972019-03-04 22:45:36 +08004422 // ... and that stopping it after that has no adverse effects.
4423 waitForIdle();
4424 final Network myNetAlias = myNet;
4425 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4426 ka.stop();
4427 callback.assertNoCallback();
4428 }
junyulai48eac1d42018-12-27 17:25:29 +08004429
4430 // Reconnect.
4431 myNet = connectKeepaliveNetwork(lp);
4432 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4433
4434 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4435 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004436 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004437 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4438 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4439 ka.start(validKaInterval);
4440 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004441
junyulai0c666972019-03-04 22:45:36 +08004442 // The second one gets slot 2.
4443 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004444 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4445 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004446 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4447 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4448 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4449 ka2.start(validKaInterval);
4450 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004451
junyulai0c666972019-03-04 22:45:36 +08004452 ka.stop();
4453 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004454
junyulai0c666972019-03-04 22:45:36 +08004455 ka2.stop();
4456 callback2.expectStopped();
junyulaie4135282019-01-03 18:50:15 +08004457
junyulai0c666972019-03-04 22:45:36 +08004458 testSocket.close();
4459 testSocket2.close();
4460 }
4461 }
junyulaie4135282019-01-03 18:50:15 +08004462
junyulai15178152019-03-27 11:00:37 +08004463 // Check that there is no port leaked after all keepalives and sockets are closed.
Junyu Laifd850fd2019-04-15 23:00:02 -07004464 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4465 // assertFalse(isUdpPortInUse(srcPort));
4466 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004467
junyulaie4135282019-01-03 18:50:15 +08004468 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004469 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
Xiao Maa4637112019-02-07 15:03:57 +09004470 mWiFiNetworkAgent = null;
4471 }
4472
4473 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004474 public void testTcpSocketKeepalives() throws Exception {
4475 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004476 }
4477
4478 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4479 final int srcPortV4 = 12345;
4480 final int srcPortV6 = 23456;
4481 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4482 final InetAddress myIPv6 = InetAddress.getByName("::1");
4483
4484 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004485
4486 final LinkProperties lp = new LinkProperties();
4487 lp.setInterfaceName("wlan12");
4488 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4489 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4490 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4491 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4492
4493 final Network notMyNet = new Network(61234);
4494 final Network myNet = connectKeepaliveNetwork(lp);
4495
4496 final Socket testSocketV4 = new Socket();
4497 final Socket testSocketV6 = new Socket();
4498
junyulai7c469172019-01-16 20:23:34 +08004499 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004500
4501 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4502 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004503 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4504 notMyNet, testSocketV4, executor, callback)) {
4505 ka.start(validKaInterval);
4506 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4507 }
Xiao Maa4637112019-02-07 15:03:57 +09004508
4509 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004510 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4511 myNet, testSocketV4, executor, callback)) {
4512 ka.start(validKaInterval);
4513 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4514 }
Xiao Maa4637112019-02-07 15:03:57 +09004515
4516 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004517 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4518 myNet, testSocketV6, executor, callback)) {
4519 ka.start(validKaInterval);
4520 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4521 }
Xiao Maa4637112019-02-07 15:03:57 +09004522
4523 // Bind the socket address
4524 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4525 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4526
4527 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004528 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4529 myNet, testSocketV4, executor, callback)) {
4530 ka.start(validKaInterval);
4531 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4532 }
Xiao Maa4637112019-02-07 15:03:57 +09004533
4534 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004535 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4536 myNet, testSocketV6, executor, callback)) {
4537 ka.start(validKaInterval);
4538 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4539 }
Xiao Maa4637112019-02-07 15:03:57 +09004540
4541 testSocketV4.close();
4542 testSocketV6.close();
4543
4544 mWiFiNetworkAgent.disconnect();
4545 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4546 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004547 }
4548
junyulai0c666972019-03-04 22:45:36 +08004549 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004550 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4551 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4552 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4553 final int validKaInterval = 15;
4554
4555 // Prepare the target network.
4556 LinkProperties lp = new LinkProperties();
4557 lp.setInterfaceName("wlan12");
4558 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4559 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4560 Network myNet = connectKeepaliveNetwork(lp);
4561 mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
4562 mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
4563
4564 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4565
4566 // Prepare the target file descriptor, keep only one instance.
4567 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004568 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4569 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004570 final ParcelFileDescriptor testPfd =
4571 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4572 testSocket.close();
4573 assertTrue(isUdpPortInUse(srcPort));
4574
4575 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4576 // block.
4577 try (SocketKeepalive ka = mCm.createNattKeepalive(
4578 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4579 ka.start(validKaInterval);
4580 callback.expectStarted();
4581 ka.stop();
4582 callback.expectStopped();
4583 }
4584
4585 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4586 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4587 // address.
4588 assertTrue(isUdpPortInUse(srcPort));
4589 final InetSocketAddress sa =
4590 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4591 assertEquals(anyIPv4, sa.getAddress());
4592
4593 testPfd.close();
Junyu Laifd850fd2019-04-15 23:00:02 -07004594 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4595 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004596
4597 mWiFiNetworkAgent.disconnect();
4598 waitFor(mWiFiNetworkAgent.getDisconnectedCV());
4599 mWiFiNetworkAgent = null;
4600 }
4601
4602 private static boolean isUdpPortInUse(int port) {
4603 try (DatagramSocket ignored = new DatagramSocket(port)) {
4604 return false;
4605 } catch (IOException ignored) {
4606 return true;
4607 }
4608 }
4609
junyulai48eac1d42018-12-27 17:25:29 +08004610 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004611 public void testGetCaptivePortalServerUrl() throws Exception {
4612 String url = mCm.getCaptivePortalServerUrl();
4613 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4614 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004615
4616 private static class TestNetworkPinner extends NetworkPinner {
4617 public static boolean awaitPin(int timeoutMs) {
4618 synchronized(sLock) {
4619 if (sNetwork == null) {
4620 try {
4621 sLock.wait(timeoutMs);
4622 } catch (InterruptedException e) {}
4623 }
4624 return sNetwork != null;
4625 }
4626 }
4627
4628 public static boolean awaitUnpin(int timeoutMs) {
4629 synchronized(sLock) {
4630 if (sNetwork != null) {
4631 try {
4632 sLock.wait(timeoutMs);
4633 } catch (InterruptedException e) {}
4634 }
4635 return sNetwork == null;
4636 }
4637 }
4638 }
4639
4640 private void assertPinnedToWifiWithCellDefault() {
4641 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4642 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4643 }
4644
4645 private void assertPinnedToWifiWithWifiDefault() {
4646 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4647 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4648 }
4649
4650 private void assertNotPinnedToWifi() {
4651 assertNull(mCm.getBoundNetworkForProcess());
4652 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4653 }
4654
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004655 @Test
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004656 public void testNetworkPinner() {
4657 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4658 .addTransportType(TRANSPORT_WIFI)
4659 .build();
4660 assertNull(mCm.getBoundNetworkForProcess());
4661
4662 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4663 assertNull(mCm.getBoundNetworkForProcess());
4664
4665 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
4666 mCellNetworkAgent.connect(true);
4667 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4668 mWiFiNetworkAgent.connect(false);
4669
4670 // When wi-fi connects, expect to be pinned.
4671 assertTrue(TestNetworkPinner.awaitPin(100));
4672 assertPinnedToWifiWithCellDefault();
4673
4674 // Disconnect and expect the pin to drop.
4675 mWiFiNetworkAgent.disconnect();
4676 assertTrue(TestNetworkPinner.awaitUnpin(100));
4677 assertNotPinnedToWifi();
4678
4679 // Reconnecting does not cause the pin to come back.
4680 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4681 mWiFiNetworkAgent.connect(false);
4682 assertFalse(TestNetworkPinner.awaitPin(100));
4683 assertNotPinnedToWifi();
4684
4685 // Pinning while connected causes the pin to take effect immediately.
4686 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4687 assertTrue(TestNetworkPinner.awaitPin(100));
4688 assertPinnedToWifiWithCellDefault();
4689
4690 // Explicitly unpin and expect to use the default network again.
4691 TestNetworkPinner.unpin();
4692 assertNotPinnedToWifi();
4693
4694 // Disconnect cell and wifi.
4695 ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
4696 mCellNetworkAgent.disconnect();
4697 mWiFiNetworkAgent.disconnect();
4698 waitFor(cv);
4699
4700 // Pinning takes effect even if the pinned network is the default when the pin is set...
4701 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4702 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4703 mWiFiNetworkAgent.connect(false);
4704 assertTrue(TestNetworkPinner.awaitPin(100));
4705 assertPinnedToWifiWithWifiDefault();
4706
4707 // ... and is maintained even when that network is no longer the default.
4708 cv = waitForConnectivityBroadcasts(1);
4709 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4710 mCellNetworkAgent.connect(true);
4711 waitFor(cv);
4712 assertPinnedToWifiWithCellDefault();
4713 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004714
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004715 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004716 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004717 // We can only have 99 callbacks, because MultipathPolicyTracker is
4718 // already one of them.
4719 final int MAX_REQUESTS = 99;
4720 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004721 final int INTENTS = 10;
4722 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4723
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004724 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004725 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004726
Hugo Benichi893a7622017-09-29 09:34:08 +09004727 int j = 0;
4728 while (j++ < CALLBACKS / 2) {
4729 NetworkCallback cb = new NetworkCallback();
4730 mCm.requestNetwork(networkRequest, cb);
4731 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004732 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004733 while (j++ < CALLBACKS) {
4734 NetworkCallback cb = new NetworkCallback();
4735 mCm.registerNetworkCallback(networkRequest, cb);
4736 registered.add(cb);
4737 }
4738 j = 0;
4739 while (j++ < INTENTS / 2) {
4740 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4741 mCm.requestNetwork(networkRequest, pi);
4742 registered.add(pi);
4743 }
4744 while (j++ < INTENTS) {
4745 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4746 mCm.registerNetworkCallback(networkRequest, pi);
4747 registered.add(pi);
4748 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004749
Hugo Benichi893a7622017-09-29 09:34:08 +09004750 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004751 try {
Hugo Benichi893a7622017-09-29 09:34:08 +09004752 mCm.requestNetwork(networkRequest, new NetworkCallback());
4753 fail("Registering " + MAX_REQUESTS + " network requests did not throw exception");
Hugo Benichicb883232017-05-11 13:16:17 +09004754 } catch (TooManyRequestsException expected) {}
Hugo Benichi893a7622017-09-29 09:34:08 +09004755 try {
4756 mCm.registerNetworkCallback(networkRequest, new NetworkCallback());
4757 fail("Registering " + MAX_REQUESTS + " network callbacks did not throw exception");
4758 } catch (TooManyRequestsException expected) {}
4759 try {
4760 mCm.requestNetwork(networkRequest,
4761 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0));
4762 fail("Registering " + MAX_REQUESTS + " PendingIntent requests did not throw exception");
4763 } catch (TooManyRequestsException expected) {}
4764 try {
4765 mCm.registerNetworkCallback(networkRequest,
4766 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0));
4767 fail("Registering " + MAX_REQUESTS
4768 + " PendingIntent callbacks did not throw exception");
4769 } catch (TooManyRequestsException expected) {}
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004770
Hugo Benichi893a7622017-09-29 09:34:08 +09004771 for (Object o : registered) {
4772 if (o instanceof NetworkCallback) {
4773 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004774 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004775 if (o instanceof PendingIntent) {
4776 mCm.unregisterNetworkCallback((PendingIntent)o);
4777 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004778 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004779 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004780
4781 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4782 for (int i = 0; i < MAX_REQUESTS; i++) {
4783 NetworkCallback networkCallback = new NetworkCallback();
4784 mCm.requestNetwork(networkRequest, networkCallback);
4785 mCm.unregisterNetworkCallback(networkCallback);
4786 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004787 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004788
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004789 for (int i = 0; i < MAX_REQUESTS; i++) {
4790 NetworkCallback networkCallback = new NetworkCallback();
4791 mCm.registerNetworkCallback(networkRequest, networkCallback);
4792 mCm.unregisterNetworkCallback(networkCallback);
4793 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004794 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004795
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004796 for (int i = 0; i < MAX_REQUESTS; i++) {
4797 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004798 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004799 mCm.requestNetwork(networkRequest, pendingIntent);
4800 mCm.unregisterNetworkCallback(pendingIntent);
4801 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004802 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004803
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004804 for (int i = 0; i < MAX_REQUESTS; i++) {
4805 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004806 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004807 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4808 mCm.unregisterNetworkCallback(pendingIntent);
4809 }
4810 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004811
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004812 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004813 public void testNetworkInfoOfTypeNone() {
4814 ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
4815
4816 verifyNoNetwork();
Hugo Benichic1014502017-07-19 10:10:52 +09004817 MockNetworkAgent wifiAware = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004818 assertNull(mCm.getActiveNetworkInfo());
4819
4820 Network[] allNetworks = mCm.getAllNetworks();
4821 assertLength(1, allNetworks);
4822 Network network = allNetworks[0];
4823 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4824 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4825
4826 final NetworkRequest request =
4827 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4828 final TestNetworkCallback callback = new TestNetworkCallback();
4829 mCm.registerNetworkCallback(request, callback);
4830
Hugo Benichic1014502017-07-19 10:10:52 +09004831 // Bring up wifi aware network.
4832 wifiAware.connect(false, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004833 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004834
4835 assertNull(mCm.getActiveNetworkInfo());
4836 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004837 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004838 // of this test. Fix it and uncomment the assert below.
4839 //assertEmpty(mCm.getAllNetworkInfo());
4840
Hugo Benichic1014502017-07-19 10:10:52 +09004841 // Disconnect wifi aware network.
4842 wifiAware.disconnect();
4843 callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004844 mCm.unregisterNetworkCallback(callback);
4845
4846 verifyNoNetwork();
4847 if (broadcastCV.block(10)) {
4848 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4849 }
4850 }
4851
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004852 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004853 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4854 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4855 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4856 assertNull(mCm.getNetworkForType(TYPE_NONE));
4857 assertNull(mCm.getLinkProperties(TYPE_NONE));
4858 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4859
4860 assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
4861 IllegalArgumentException.class);
4862
4863 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
4864 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4865 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
4866 // TODO: let test context have configuration application target sdk version
4867 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
4868 assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4869 assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
4870 assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
4871 }
4872
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004873 @Test
Rubin Xu1bb5c082017-09-05 18:40:49 +01004874 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
4875 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4876 .addTransportType(TRANSPORT_WIFI).build();
4877 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4878 mCm.registerNetworkCallback(networkRequest, networkCallback);
4879
4880 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004881 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004882 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4883 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4884 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4885 lp.addLinkAddress(myIpv4Address);
4886 lp.addRoute(myIpv4DefaultRoute);
4887
4888 // Verify direct routes are added when network agent is first registered in
4889 // ConnectivityService.
4890 MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
4891 networkAgent.connect(true);
4892 networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
4893 networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
4894 CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
4895 networkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08004896 networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004897 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4898 networkCallback.assertNoCallback();
4899 checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
4900 Arrays.asList(myIpv4DefaultRoute));
4901 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4902 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4903
4904 // Verify direct routes are added during subsequent link properties updates.
4905 LinkProperties newLp = new LinkProperties(lp);
4906 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4907 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4908 newLp.addLinkAddress(myIpv6Address1);
4909 newLp.addLinkAddress(myIpv6Address2);
4910 networkAgent.sendLinkProperties(newLp);
4911 cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
4912 networkCallback.assertNoCallback();
4913 checkDirectlyConnectedRoutes(cbi.arg,
4914 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4915 Arrays.asList(myIpv4DefaultRoute));
4916 mCm.unregisterNetworkCallback(networkCallback);
4917 }
4918
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004919 @Test
4920 public void testStatsIfacesChanged() throws Exception {
4921 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004922 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
4923
Varun Anand02c50ef2019-02-07 14:13:13 -08004924 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4925 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4926
4927 LinkProperties cellLp = new LinkProperties();
4928 cellLp.setInterfaceName(MOBILE_IFNAME);
4929 LinkProperties wifiLp = new LinkProperties();
4930 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004931
4932 // Simple connection should have updated ifaces
4933 mCellNetworkAgent.connect(false);
Varun Anand02c50ef2019-02-07 14:13:13 -08004934 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004935 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004936 verify(mStatsService, atLeastOnce())
4937 .forceUpdateIfaces(
4938 eq(onlyCell),
4939 eq(new VpnInfo[0]),
4940 any(NetworkState[].class),
4941 eq(MOBILE_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004942 reset(mStatsService);
4943
4944 // Default network switch should update ifaces.
4945 mWiFiNetworkAgent.connect(false);
Varun Anand02c50ef2019-02-07 14:13:13 -08004946 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004947 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004948 assertEquals(wifiLp, mService.getActiveLinkProperties());
4949 verify(mStatsService, atLeastOnce())
4950 .forceUpdateIfaces(
4951 eq(onlyWifi),
4952 eq(new VpnInfo[0]),
4953 any(NetworkState[].class),
4954 eq(WIFI_IFNAME));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004955 reset(mStatsService);
4956
4957 // Disconnect should update ifaces.
4958 mWiFiNetworkAgent.disconnect();
4959 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004960 verify(mStatsService, atLeastOnce())
4961 .forceUpdateIfaces(
4962 eq(onlyCell),
4963 eq(new VpnInfo[0]),
4964 any(NetworkState[].class),
4965 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004966 reset(mStatsService);
4967
4968 // Metered change should update ifaces
4969 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4970 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004971 verify(mStatsService, atLeastOnce())
4972 .forceUpdateIfaces(
4973 eq(onlyCell),
4974 eq(new VpnInfo[0]),
4975 any(NetworkState[].class),
4976 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004977 reset(mStatsService);
4978
4979 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4980 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004981 verify(mStatsService, atLeastOnce())
4982 .forceUpdateIfaces(
4983 eq(onlyCell),
4984 eq(new VpnInfo[0]),
4985 any(NetworkState[].class),
4986 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004987 reset(mStatsService);
4988
4989 // Captive portal change shouldn't update ifaces
4990 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4991 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08004992 verify(mStatsService, never())
4993 .forceUpdateIfaces(
4994 eq(onlyCell),
4995 eq(new VpnInfo[0]),
4996 any(NetworkState[].class),
4997 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004998 reset(mStatsService);
4999
5000 // Roaming change should update ifaces
5001 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
5002 waitForIdle();
Varun Anand02c50ef2019-02-07 14:13:13 -08005003 verify(mStatsService, atLeastOnce())
5004 .forceUpdateIfaces(
5005 eq(onlyCell),
5006 eq(new VpnInfo[0]),
5007 any(NetworkState[].class),
5008 eq(MOBILE_IFNAME));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06005009 reset(mStatsService);
5010 }
5011
Erik Klinee89953b2018-01-11 16:11:10 +09005012 @Test
5013 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07005014 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07005015
5016 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08005017 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005018
Erik Klinee89953b2018-01-11 16:11:10 +09005019 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5020 waitForIdle();
Wayne Ma28417f42019-04-17 08:03:59 -07005021 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005022 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005023
5024 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07005025 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09005026 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5027 // "is-reachable" testing in order to not program netd with unreachable
5028 // nameservers that it might try repeated to validate.
5029 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07005030 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5031 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09005032 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07005033 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5034 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09005035 mCellNetworkAgent.sendLinkProperties(cellLp);
5036 mCellNetworkAgent.connect(false);
5037 waitForIdle();
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07005038
5039 verify(mMockDnsResolver, times(1)).createNetworkCache(
5040 eq(mCellNetworkAgent.getNetwork().netId));
5041 // CS tells dnsresolver about the empty DNS config for this network.
Wayne Ma28417f42019-04-17 08:03:59 -07005042 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005043 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005044
5045 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5046 mCellNetworkAgent.sendLinkProperties(cellLp);
5047 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005048 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005049 mResolverParamsParcelCaptor.capture());
5050 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5051 assertEquals(1, resolvrParams.servers.length);
5052 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07005053 // Opportunistic mode.
Wayne Ma28417f42019-04-17 08:03:59 -07005054 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08005055 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005056
5057 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5058 mCellNetworkAgent.sendLinkProperties(cellLp);
5059 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005060 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005061 mResolverParamsParcelCaptor.capture());
5062 resolvrParams = mResolverParamsParcelCaptor.getValue();
5063 assertEquals(2, resolvrParams.servers.length);
5064 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09005065 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07005066 // Opportunistic mode.
Wayne Ma28417f42019-04-17 08:03:59 -07005067 assertEquals(2, resolvrParams.tlsServers.length);
5068 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005069 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005070 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09005071
5072 final String TLS_SPECIFIER = "tls.example.com";
5073 final String TLS_SERVER6 = "2001:db8:53::53";
5074 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
5075 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005076 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
5077 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
5078
Erik Kline117e7f32018-03-04 21:01:01 +09005079 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005080 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005081 mResolverParamsParcelCaptor.capture());
5082 resolvrParams = mResolverParamsParcelCaptor.getValue();
5083 assertEquals(2, resolvrParams.servers.length);
5084 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09005085 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005086 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005087 }
5088
Erik Kline79c6d052018-03-21 07:18:33 -07005089 @Test
5090 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07005091 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08005092 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005093
5094 // The default on Android is opportunistic mode ("Automatic").
5095 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5096
dalyk1fcb7392018-03-05 12:42:22 -05005097 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5098 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5099 .addTransportType(TRANSPORT_CELLULAR).build();
5100 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5101
Erik Kline79c6d052018-03-21 07:18:33 -07005102 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5103 waitForIdle();
5104 // CS tells netd about the empty DNS config for this network.
Wayne Ma28417f42019-04-17 08:03:59 -07005105 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005106 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005107
5108 final LinkProperties cellLp = new LinkProperties();
5109 cellLp.setInterfaceName(MOBILE_IFNAME);
5110 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5111 // "is-reachable" testing in order to not program netd with unreachable
5112 // nameservers that it might try repeated to validate.
5113 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
5114 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5115 MOBILE_IFNAME));
5116 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
5117 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5118 MOBILE_IFNAME));
5119 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5120 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5121
5122 mCellNetworkAgent.sendLinkProperties(cellLp);
5123 mCellNetworkAgent.connect(false);
5124 waitForIdle();
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07005125 verify(mMockDnsResolver, times(1)).createNetworkCache(
5126 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08005127 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005128 mResolverParamsParcelCaptor.capture());
5129 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5130 assertEquals(2, resolvrParams.tlsServers.length);
5131 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005132 new String[]{"2001:db8::1", "192.0.2.1"}));
5133 // Opportunistic mode.
Wayne Ma28417f42019-04-17 08:03:59 -07005134 assertEquals(2, resolvrParams.tlsServers.length);
5135 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005136 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005137 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005138 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5139 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5140 mCellNetworkAgent);
5141 CallbackInfo cbi = cellNetworkCallback.expectCallback(
5142 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005143 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005144 cellNetworkCallback.assertNoCallback();
5145 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5146 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07005147
5148 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005149 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005150 mResolverParamsParcelCaptor.capture());
5151 resolvrParams = mResolverParamsParcelCaptor.getValue();
5152 assertEquals(2, resolvrParams.servers.length);
5153 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline79c6d052018-03-21 07:18:33 -07005154 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005155 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005156 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005157
5158 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005159 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07005160 mResolverParamsParcelCaptor.capture());
5161 resolvrParams = mResolverParamsParcelCaptor.getValue();
5162 assertEquals(2, resolvrParams.servers.length);
5163 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline79c6d052018-03-21 07:18:33 -07005164 new String[]{"2001:db8::1", "192.0.2.1"}));
Wayne Ma28417f42019-04-17 08:03:59 -07005165 assertEquals(2, resolvrParams.tlsServers.length);
5166 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005167 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005168 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005169 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005170
dalyk1fcb7392018-03-05 12:42:22 -05005171 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5172 // Can't test dns configuration for strict mode without properly mocking
5173 // out the DNS lookups, but can test that LinkProperties is updated.
5174 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5175 mCellNetworkAgent);
5176 cellNetworkCallback.assertNoCallback();
5177 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5178 assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
5179 }
5180
5181 @Test
5182 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5183 // The default on Android is opportunistic mode ("Automatic").
5184 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5185
5186 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5187 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5188 .addTransportType(TRANSPORT_CELLULAR).build();
5189 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5190
5191 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5192 waitForIdle();
5193 LinkProperties lp = new LinkProperties();
5194 mCellNetworkAgent.sendLinkProperties(lp);
5195 mCellNetworkAgent.connect(false);
5196 waitForIdle();
5197 cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
5198 cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
5199 mCellNetworkAgent);
5200 CallbackInfo cbi = cellNetworkCallback.expectCallback(
5201 CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005202 cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005203 cellNetworkCallback.assertNoCallback();
5204 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5205 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5206 Set<InetAddress> dnsServers = new HashSet<>();
5207 checkDnsServers(cbi.arg, dnsServers);
5208
5209 // Send a validation event for a server that is not part of the current
5210 // resolver config. The validation event should be ignored.
5211 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5212 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5213 cellNetworkCallback.assertNoCallback();
5214
5215 // Add a dns server to the LinkProperties.
5216 LinkProperties lp2 = new LinkProperties(lp);
5217 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5218 mCellNetworkAgent.sendLinkProperties(lp2);
5219 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5220 mCellNetworkAgent);
5221 cellNetworkCallback.assertNoCallback();
5222 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5223 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5224 dnsServers.add(InetAddress.getByName("145.100.185.16"));
5225 checkDnsServers(cbi.arg, dnsServers);
5226
5227 // Send a validation event containing a hostname that is not part of
5228 // the current resolver config. The validation event should be ignored.
5229 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5230 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5231 cellNetworkCallback.assertNoCallback();
5232
5233 // Send a validation event where validation failed.
5234 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5235 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5236 cellNetworkCallback.assertNoCallback();
5237
5238 // Send a validation event where validation succeeded for a server in
5239 // the current resolver config. A LinkProperties callback with updated
5240 // private dns fields should be sent.
5241 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5242 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
5243 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5244 mCellNetworkAgent);
5245 cellNetworkCallback.assertNoCallback();
5246 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5247 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5248 checkDnsServers(cbi.arg, dnsServers);
5249
5250 // The private dns fields in LinkProperties should be preserved when
5251 // the network agent sends unrelated changes.
5252 LinkProperties lp3 = new LinkProperties(lp2);
5253 lp3.setMtu(1300);
5254 mCellNetworkAgent.sendLinkProperties(lp3);
5255 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5256 mCellNetworkAgent);
5257 cellNetworkCallback.assertNoCallback();
5258 assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
5259 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5260 checkDnsServers(cbi.arg, dnsServers);
5261 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
5262
5263 // Removing the only validated server should affect the private dns
5264 // fields in LinkProperties.
5265 LinkProperties lp4 = new LinkProperties(lp3);
5266 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5267 mCellNetworkAgent.sendLinkProperties(lp4);
5268 cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
5269 mCellNetworkAgent);
5270 cellNetworkCallback.assertNoCallback();
5271 assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
5272 assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
5273 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
5274 checkDnsServers(cbi.arg, dnsServers);
5275 assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005276 }
5277
Rubin Xu1bb5c082017-09-05 18:40:49 +01005278 private void checkDirectlyConnectedRoutes(Object callbackObj,
5279 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5280 assertTrue(callbackObj instanceof LinkProperties);
5281 LinkProperties lp = (LinkProperties) callbackObj;
5282
5283 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5284 expectedRoutes.addAll(otherRoutes);
5285 for (LinkAddress address : linkAddresses) {
5286 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5287 // Duplicates in linkAddresses are considered failures
5288 assertTrue(expectedRoutes.add(localRoute));
5289 }
5290 List<RouteInfo> observedRoutes = lp.getRoutes();
5291 assertEquals(expectedRoutes.size(), observedRoutes.size());
5292 assertTrue(observedRoutes.containsAll(expectedRoutes));
5293 }
5294
dalyk1fcb7392018-03-05 12:42:22 -05005295 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5296 assertTrue(callbackObj instanceof LinkProperties);
5297 LinkProperties lp = (LinkProperties) callbackObj;
5298 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5299 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5300 }
5301
Hugo Benichifed512a2017-06-26 10:06:49 +09005302 private static <T> void assertEmpty(T[] ts) {
5303 int length = ts.length;
5304 assertEquals("expected empty array, but length was " + length, 0, length);
5305 }
5306
5307 private static <T> void assertLength(int expected, T[] got) {
5308 int length = got.length;
5309 assertEquals(String.format("expected array of length %s, but length was %s for %s",
5310 expected, length, Arrays.toString(got)), expected, length);
5311 }
Hugo Benichi16f0a942017-06-20 14:07:59 +09005312
5313 private static <T> void assertException(Runnable block, Class<T> expected) {
5314 try {
5315 block.run();
5316 fail("Expected exception of type " + expected);
5317 } catch (Exception got) {
5318 if (!got.getClass().equals(expected)) {
5319 fail("Expected exception of type " + expected + " but got " + got);
5320 }
5321 return;
5322 }
5323 }
Chalard Jean0b214af2018-01-12 17:22:49 +09005324
5325 @Test
5326 public void testVpnNetworkActive() {
5327 final int uid = Process.myUid();
5328
5329 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005330 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005331 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5332 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005333 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005334 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5335 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5336 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005337 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5338 .addTransportType(TRANSPORT_WIFI).build();
5339 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005340 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005341 .addTransportType(TRANSPORT_VPN).build();
5342 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005343 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005344 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5345 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005346 mCm.registerDefaultNetworkCallback(defaultCallback);
5347 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005348
5349 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5350 mWiFiNetworkAgent.connect(false);
5351
5352 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005353 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005354 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005355 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005356 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005357 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005358
5359 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5360 final ArraySet<UidRange> ranges = new ArraySet<>();
5361 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005362 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5363 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005364 // VPN networks do not satisfy the default request and are automatically validated
5365 // by NetworkMonitor
Lorenzo Colittied3168e2019-01-23 17:54:08 +09005366 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005367 vpnNetworkAgent.setNetworkValid();
5368
Chalard Jean0b214af2018-01-12 17:22:49 +09005369 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005370 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005371 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005372
5373 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005374 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005375 wifiNetworkCallback.assertNoCallback();
5376 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005377 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5378 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005379
5380 genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005381 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jeanf19db372018-01-26 19:24:40 +09005382 vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005383 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5384 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005385
5386 ranges.clear();
5387 vpnNetworkAgent.setUids(ranges);
5388
5389 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005390 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005391 wifiNetworkCallback.assertNoCallback();
5392 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5393
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005394 // TODO : The default network callback should actually get a LOST call here (also see the
5395 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5396 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5397 // can't currently update their UIDs without disconnecting, so this does not matter too
5398 // much, but that is the reason the test here has to check for an update to the
5399 // capabilities instead of the expected LOST then AVAILABLE.
5400 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5401
Chalard Jean0b214af2018-01-12 17:22:49 +09005402 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005403 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005404 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005405
5406 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005407 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005408 wifiNetworkCallback.assertNoCallback();
5409 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005410 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5411 // happen outside of the test, ConnectivityService does not rematch callbacks.
5412 defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005413
5414 mWiFiNetworkAgent.disconnect();
5415
5416 genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005417 genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005418 wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5419 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005420 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005421
5422 vpnNetworkAgent.disconnect();
5423
5424 genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005425 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005426 wifiNetworkCallback.assertNoCallback();
5427 vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005428 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5429 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005430
5431 mCm.unregisterNetworkCallback(genericNetworkCallback);
5432 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5433 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005434 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005435 }
Chalard Jean26400492018-04-18 20:18:38 +09005436
5437 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005438 public void testVpnWithoutInternet() {
Chalard Jean26400492018-04-18 20:18:38 +09005439 final int uid = Process.myUid();
5440
5441 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5442 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005443
5444 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5445 mWiFiNetworkAgent.connect(true);
5446
5447 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5448 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5449
5450 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5451 final ArraySet<UidRange> ranges = new ArraySet<>();
5452 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005453 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5454 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005455 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005456 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005457
5458 defaultCallback.assertNoCallback();
5459 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5460
5461 vpnNetworkAgent.disconnect();
5462 defaultCallback.assertNoCallback();
5463
Varun Anand4fa80e82019-02-06 10:13:38 -08005464 mCm.unregisterNetworkCallback(defaultCallback);
5465 }
5466
5467 @Test
5468 public void testVpnWithInternet() {
5469 final int uid = Process.myUid();
5470
5471 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5472 mCm.registerDefaultNetworkCallback(defaultCallback);
5473
5474 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5475 mWiFiNetworkAgent.connect(true);
5476
5477 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5478 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5479
5480 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5481 final ArraySet<UidRange> ranges = new ArraySet<>();
5482 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005483 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5484 mMockVpn.setUids(ranges);
Chalard Jean26400492018-04-18 20:18:38 +09005485 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005486 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005487
Chalard Jean26400492018-04-18 20:18:38 +09005488 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5489 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5490
5491 vpnNetworkAgent.disconnect();
5492 defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5493 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5494
Chalard Jean26400492018-04-18 20:18:38 +09005495 mCm.unregisterNetworkCallback(defaultCallback);
5496 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005497
5498 @Test
Chalard Jeanf9861102019-05-10 04:33:43 -07005499 public void testVpnUnvalidated() throws Exception {
5500 final TestNetworkCallback callback = new TestNetworkCallback();
5501 mCm.registerDefaultNetworkCallback(callback);
5502
5503 // Bring up Ethernet.
5504 mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
5505 mEthernetNetworkAgent.connect(true);
5506 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5507 callback.assertNoCallback();
5508
5509 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5510 final int uid = Process.myUid();
5511 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5512 final ArraySet<UidRange> ranges = new ArraySet<>();
5513 ranges.add(new UidRange(uid, uid));
5514 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5515 mMockVpn.setUids(ranges);
5516 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
5517 mMockVpn.connect();
5518
5519 // Even though the VPN is unvalidated, it becomes the default network for our app.
5520 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5521 // TODO: this looks like a spurious callback.
5522 callback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
5523 callback.assertNoCallback();
5524
5525 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5526 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5527 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5528
5529 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5530 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5531 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5532
5533 assertFalse(NetworkMonitorUtils.isValidationRequired(vpnNetworkAgent.mNetworkCapabilities));
5534 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
5535 vpnNetworkAgent.mNetworkCapabilities));
5536
5537 // Pretend that the VPN network validates.
5538 vpnNetworkAgent.setNetworkValid();
5539 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5540 // Expect to see the validated capability, but no other changes, because the VPN is already
5541 // the default network for the app.
5542 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5543 callback.assertNoCallback();
5544
5545 vpnNetworkAgent.disconnect();
5546 callback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
5547 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5548 }
5549
5550 @Test
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005551 public void testVpnSetUnderlyingNetworks() {
5552 final int uid = Process.myUid();
5553
5554 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5555 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5556 .removeCapability(NET_CAPABILITY_NOT_VPN)
5557 .addTransportType(TRANSPORT_VPN)
5558 .build();
5559 NetworkCapabilities nc;
5560 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5561 vpnNetworkCallback.assertNoCallback();
5562
5563 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5564 final ArraySet<UidRange> ranges = new ArraySet<>();
5565 ranges.add(new UidRange(uid, uid));
5566 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5567 mMockVpn.connect();
5568 mMockVpn.setUids(ranges);
5569 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5570
5571 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5572 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5573 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5574 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5575 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5576 // For safety reasons a VPN without underlying networks is considered metered.
5577 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5578
5579 // Connect cell and use it as an underlying network.
5580 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5581 mCellNetworkAgent.connect(true);
5582
5583 mService.setUnderlyingNetworksForVpn(
5584 new Network[] { mCellNetworkAgent.getNetwork() });
5585
5586 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5587 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5588 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5589 vpnNetworkAgent);
5590
5591 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5592 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5593 mWiFiNetworkAgent.connect(true);
5594
5595 mService.setUnderlyingNetworksForVpn(
5596 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5597
5598 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5599 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5600 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5601 vpnNetworkAgent);
5602
5603 // Don't disconnect, but note the VPN is not using wifi any more.
5604 mService.setUnderlyingNetworksForVpn(
5605 new Network[] { mCellNetworkAgent.getNetwork() });
5606
5607 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5608 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5609 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5610 vpnNetworkAgent);
5611
5612 // Use Wifi but not cell. Note the VPN is now unmetered.
5613 mService.setUnderlyingNetworksForVpn(
5614 new Network[] { mWiFiNetworkAgent.getNetwork() });
5615
5616 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5617 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5618 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5619 vpnNetworkAgent);
5620
5621 // Use both again.
5622 mService.setUnderlyingNetworksForVpn(
5623 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5624
5625 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5626 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5627 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5628 vpnNetworkAgent);
5629
Chalard Jean6b65ec72018-05-18 22:02:56 +09005630 // Disconnect cell. Receive update without even removing the dead network from the
5631 // underlying networks – it's dead anyway. Not metered any more.
5632 mCellNetworkAgent.disconnect();
5633 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5634 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5635 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5636 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005637
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005638 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005639 mWiFiNetworkAgent.disconnect();
5640 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5641 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005642 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
Chalard Jean6b65ec72018-05-18 22:02:56 +09005643 vpnNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005644
5645 mMockVpn.disconnect();
5646 }
junyulai4a192e22018-06-13 15:00:37 +08005647
Mike Yuf9729752018-08-17 15:22:05 +08005648 @Test
Varun Anand4fa80e82019-02-06 10:13:38 -08005649 public void testNullUnderlyingNetworks() {
5650 final int uid = Process.myUid();
5651
5652 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5653 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5654 .removeCapability(NET_CAPABILITY_NOT_VPN)
5655 .addTransportType(TRANSPORT_VPN)
5656 .build();
5657 NetworkCapabilities nc;
5658 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5659 vpnNetworkCallback.assertNoCallback();
5660
5661 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5662 final ArraySet<UidRange> ranges = new ArraySet<>();
5663 ranges.add(new UidRange(uid, uid));
5664 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5665 mMockVpn.connect();
5666 mMockVpn.setUids(ranges);
5667 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
5668
5669 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5670 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5671 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5672 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5673 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5674 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5675 // In case of no default network, VPN is considered metered.
5676 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5677
5678 // Connect to Cell; Cell is the default network.
5679 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5680 mCellNetworkAgent.connect(true);
5681
5682 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5683 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5684 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5685 vpnNetworkAgent);
5686
5687 // Connect to WiFi; WiFi is the new default.
5688 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5689 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5690 mWiFiNetworkAgent.connect(true);
5691
5692 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5693 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5694 && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5695 vpnNetworkAgent);
5696
5697 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5698 // the capabilities.
5699 mCellNetworkAgent.disconnect();
5700
5701 // Disconnect wifi too. Now we have no default network.
5702 mWiFiNetworkAgent.disconnect();
5703
5704 vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
5705 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5706 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
5707 vpnNetworkAgent);
5708
5709 mMockVpn.disconnect();
5710 }
5711
5712 @Test
Varun Anandc51b06d2019-02-25 17:22:02 -08005713 public void testIsActiveNetworkMeteredOverWifi() {
5714 // Returns true by default when no network is available.
5715 assertTrue(mCm.isActiveNetworkMetered());
5716 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5717 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5718 mWiFiNetworkAgent.connect(true);
5719 waitForIdle();
5720
5721 assertFalse(mCm.isActiveNetworkMetered());
5722 }
5723
5724 @Test
5725 public void testIsActiveNetworkMeteredOverCell() {
5726 // Returns true by default when no network is available.
5727 assertTrue(mCm.isActiveNetworkMetered());
5728 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5729 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5730 mCellNetworkAgent.connect(true);
5731 waitForIdle();
5732
5733 assertTrue(mCm.isActiveNetworkMetered());
5734 }
5735
5736 @Test
5737 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
5738 // Returns true by default when no network is available.
5739 assertTrue(mCm.isActiveNetworkMetered());
5740 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5741 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5742 mCellNetworkAgent.connect(true);
5743 waitForIdle();
5744 assertTrue(mCm.isActiveNetworkMetered());
5745
5746 // Connect VPN network. By default it is using current default network (Cell).
5747 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5748 final ArraySet<UidRange> ranges = new ArraySet<>();
5749 final int uid = Process.myUid();
5750 ranges.add(new UidRange(uid, uid));
5751 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5752 mMockVpn.setUids(ranges);
5753 vpnNetworkAgent.connect(true);
5754 mMockVpn.connect();
5755 waitForIdle();
5756 // Ensure VPN is now the active network.
5757 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5758
5759 // Expect VPN to be metered.
5760 assertTrue(mCm.isActiveNetworkMetered());
5761
5762 // Connect WiFi.
5763 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5764 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5765 mWiFiNetworkAgent.connect(true);
5766 waitForIdle();
5767 // VPN should still be the active network.
5768 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5769
5770 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5771 assertFalse(mCm.isActiveNetworkMetered());
5772
5773 // Disconnecting Cell should not affect VPN's meteredness.
5774 mCellNetworkAgent.disconnect();
5775 waitForIdle();
5776
5777 assertFalse(mCm.isActiveNetworkMetered());
5778
5779 // Disconnect WiFi; Now there is no platform default network.
5780 mWiFiNetworkAgent.disconnect();
5781 waitForIdle();
5782
5783 // VPN without any underlying networks is treated as metered.
5784 assertTrue(mCm.isActiveNetworkMetered());
5785
5786 vpnNetworkAgent.disconnect();
5787 mMockVpn.disconnect();
5788 }
5789
5790 @Test
5791 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
5792 // Returns true by default when no network is available.
5793 assertTrue(mCm.isActiveNetworkMetered());
5794 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5795 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5796 mCellNetworkAgent.connect(true);
5797 waitForIdle();
5798 assertTrue(mCm.isActiveNetworkMetered());
5799
5800 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5801 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5802 mWiFiNetworkAgent.connect(true);
5803 waitForIdle();
5804 assertFalse(mCm.isActiveNetworkMetered());
5805
5806 // Connect VPN network.
5807 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5808 final ArraySet<UidRange> ranges = new ArraySet<>();
5809 final int uid = Process.myUid();
5810 ranges.add(new UidRange(uid, uid));
5811 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5812 mMockVpn.setUids(ranges);
5813 vpnNetworkAgent.connect(true);
5814 mMockVpn.connect();
5815 waitForIdle();
5816 // Ensure VPN is now the active network.
5817 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5818 // VPN is using Cell
5819 mService.setUnderlyingNetworksForVpn(
5820 new Network[] { mCellNetworkAgent.getNetwork() });
5821 waitForIdle();
5822
5823 // Expect VPN to be metered.
5824 assertTrue(mCm.isActiveNetworkMetered());
5825
5826 // VPN is now using WiFi
5827 mService.setUnderlyingNetworksForVpn(
5828 new Network[] { mWiFiNetworkAgent.getNetwork() });
5829 waitForIdle();
5830
5831 // Expect VPN to be unmetered
5832 assertFalse(mCm.isActiveNetworkMetered());
5833
5834 // VPN is using Cell | WiFi.
5835 mService.setUnderlyingNetworksForVpn(
5836 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5837 waitForIdle();
5838
5839 // Expect VPN to be metered.
5840 assertTrue(mCm.isActiveNetworkMetered());
5841
5842 // VPN is using WiFi | Cell.
5843 mService.setUnderlyingNetworksForVpn(
5844 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5845 waitForIdle();
5846
5847 // Order should not matter and VPN should still be metered.
5848 assertTrue(mCm.isActiveNetworkMetered());
5849
5850 // VPN is not using any underlying networks.
5851 mService.setUnderlyingNetworksForVpn(new Network[0]);
5852 waitForIdle();
5853
5854 // VPN without underlying networks is treated as metered.
5855 assertTrue(mCm.isActiveNetworkMetered());
5856
5857 vpnNetworkAgent.disconnect();
5858 mMockVpn.disconnect();
5859 }
5860
5861 @Test
5862 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
5863 // Returns true by default when no network is available.
5864 assertTrue(mCm.isActiveNetworkMetered());
5865 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5866 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5867 mWiFiNetworkAgent.connect(true);
5868 waitForIdle();
5869 assertFalse(mCm.isActiveNetworkMetered());
5870
5871 // Connect VPN network.
5872 MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
5873 final ArraySet<UidRange> ranges = new ArraySet<>();
5874 final int uid = Process.myUid();
5875 ranges.add(new UidRange(uid, uid));
5876 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5877 mMockVpn.setUids(ranges);
5878 vpnNetworkAgent.connect(true);
5879 mMockVpn.connectAsAlwaysMetered();
5880 waitForIdle();
5881 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5882
5883 // VPN is tracking current platform default (WiFi).
5884 mService.setUnderlyingNetworksForVpn(null);
5885 waitForIdle();
5886
5887 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5888 assertTrue(mCm.isActiveNetworkMetered());
5889
5890 // VPN explicitly declares WiFi as its underlying network.
5891 mService.setUnderlyingNetworksForVpn(
5892 new Network[] { mWiFiNetworkAgent.getNetwork() });
5893 waitForIdle();
5894
5895 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5896 assertTrue(mCm.isActiveNetworkMetered());
5897
5898 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5899 // anyways suppose to be metered.
5900 mWiFiNetworkAgent.disconnect();
5901 waitForIdle();
5902
5903 assertTrue(mCm.isActiveNetworkMetered());
5904
5905 vpnNetworkAgent.disconnect();
5906 }
5907
5908 @Test
Mike Yuf9729752018-08-17 15:22:05 +08005909 public void testNetworkBlockedStatus() {
5910 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5911 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5912 .addTransportType(TRANSPORT_CELLULAR)
5913 .build();
5914 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5915
5916 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5917 mCellNetworkAgent.connect(true);
5918 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5919
5920 mService.setUidRulesChanged(RULE_REJECT_ALL);
5921 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5922
5923 // ConnectivityService should cache it not to invoke the callback again.
5924 mService.setUidRulesChanged(RULE_REJECT_METERED);
5925 cellNetworkCallback.assertNoCallback();
5926
5927 mService.setUidRulesChanged(RULE_NONE);
5928 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5929
5930 mService.setUidRulesChanged(RULE_REJECT_METERED);
5931 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5932
5933 // Restrict the network based on UID rule and NOT_METERED capability change.
5934 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5935 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5936 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5937 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5938 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5939 mCellNetworkAgent);
5940 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5941 mService.setUidRulesChanged(RULE_ALLOW_METERED);
5942 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5943
5944 mService.setUidRulesChanged(RULE_NONE);
5945 cellNetworkCallback.assertNoCallback();
5946
5947 // Restrict the network based on BackgroundRestricted.
5948 mService.setRestrictBackgroundChanged(true);
5949 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5950 mService.setRestrictBackgroundChanged(true);
5951 cellNetworkCallback.assertNoCallback();
5952 mService.setRestrictBackgroundChanged(false);
5953 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5954 cellNetworkCallback.assertNoCallback();
5955
5956 mCm.unregisterNetworkCallback(cellNetworkCallback);
5957 }
5958
5959 @Test
5960 public void testNetworkBlockedStatusBeforeAndAfterConnect() {
5961 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5962 mCm.registerDefaultNetworkCallback(defaultCallback);
5963
5964 // No Networkcallbacks invoked before any network is active.
5965 mService.setUidRulesChanged(RULE_REJECT_ALL);
5966 mService.setUidRulesChanged(RULE_NONE);
5967 mService.setUidRulesChanged(RULE_REJECT_METERED);
5968 defaultCallback.assertNoCallback();
5969
5970 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
5971 mCellNetworkAgent.connect(true);
5972 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5973 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5974
5975 // Allow to use the network after switching to NOT_METERED network.
5976 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
5977 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5978 mWiFiNetworkAgent.connect(true);
5979 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5980
5981 // Switch to METERED network. Restrict the use of the network.
5982 mWiFiNetworkAgent.disconnect();
5983 defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
5984 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5985
5986 // Network becomes NOT_METERED.
5987 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5988 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5989 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5990
5991 // Verify there's no Networkcallbacks invoked after data saver on/off.
5992 mService.setRestrictBackgroundChanged(true);
5993 mService.setRestrictBackgroundChanged(false);
5994 defaultCallback.assertNoCallback();
5995
5996 mCellNetworkAgent.disconnect();
5997 defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
5998 defaultCallback.assertNoCallback();
5999
6000 mCm.unregisterNetworkCallback(defaultCallback);
6001 }
6002
junyulai4a192e22018-06-13 15:00:37 +08006003 /**
6004 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
6005 */
6006 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
6007 InterfaceConfiguration cfg = new InterfaceConfiguration();
6008 cfg.setHardwareAddress("11:22:33:44:55:66");
6009 cfg.setLinkAddress(la);
6010 return cfg;
6011 }
6012
6013 /**
6014 * Make expected stack link properties, copied from Nat464Xlat.
6015 */
6016 private LinkProperties makeClatLinkProperties(LinkAddress la) {
6017 LinkAddress clatAddress = la;
6018 LinkProperties stacked = new LinkProperties();
6019 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
6020 RouteInfo ipv4Default = new RouteInfo(
6021 new LinkAddress(Inet4Address.ANY, 0),
6022 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
6023 stacked.addRoute(ipv4Default);
6024 stacked.addLinkAddress(clatAddress);
6025 return stacked;
6026 }
6027
6028 @Test
6029 public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
6030 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
6031 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006032 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
6033 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
6034
junyulai4a192e22018-06-13 15:00:37 +08006035 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6036 .addTransportType(TRANSPORT_CELLULAR)
6037 .addCapability(NET_CAPABILITY_INTERNET)
6038 .build();
6039 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6040 mCm.registerNetworkCallback(networkRequest, networkCallback);
6041
Lorenzo Colittid593e292019-02-19 13:21:56 +09006042 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08006043 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006044 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08006045 final LinkProperties cellLp = new LinkProperties();
6046 cellLp.setInterfaceName(MOBILE_IFNAME);
6047 cellLp.addLinkAddress(myIpv6);
6048 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
6049 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
6050 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006051 reset(mMockDnsResolver);
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07006052 reset(mMockNetd);
junyulai4a192e22018-06-13 15:00:37 +08006053 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6054 .thenReturn(getClatInterfaceConfig(myIpv4));
6055
Lorenzo Colittid593e292019-02-19 13:21:56 +09006056 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08006057 mCellNetworkAgent.sendLinkProperties(cellLp);
6058 mCellNetworkAgent.connect(true);
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07006059
6060 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
6061 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
6062
junyulai4a192e22018-06-13 15:00:37 +08006063 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006064 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006065
Lorenzo Colittid593e292019-02-19 13:21:56 +09006066 // Switching default network updates TCP buffer sizes.
6067 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6068
6069 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
6070 // the NAT64 prefix was removed because one was never discovered.
6071 cellLp.addLinkAddress(myIpv4);
6072 mCellNetworkAgent.sendLinkProperties(cellLp);
6073 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006074 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
Wayne Ma28417f42019-04-17 08:03:59 -07006075 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006076
6077 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006078 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006079 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006080 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006081
6082 // Remove IPv4 address. Expect prefix discovery to be started again.
6083 cellLp.removeLinkAddress(myIpv4);
6084 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6085 mCellNetworkAgent.sendLinkProperties(cellLp);
6086 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006087 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006088
6089 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006090 Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
6091 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006092 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6093 kNat64PrefixString, 96);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006094 LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
6095 CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
6096 assertEquals(0, lpBeforeClat.getStackedLinks().size());
6097 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
6098 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6099
6100 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08006101 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006102 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006103 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
6104 .getStackedLinks();
6105 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
6106
6107 // Change trivial linkproperties and see if stacked link is preserved.
6108 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
6109 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08006110 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6111
6112 List<LinkProperties> stackedLpsAfterChange =
6113 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
6114 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
6115 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
6116
Luke Huang65914772019-03-16 00:31:46 +08006117 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
Wayne Ma28417f42019-04-17 08:03:59 -07006118 mResolverParamsParcelCaptor.capture());
6119 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6120 assertEquals(1, resolvrParams.servers.length);
6121 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08006122
Lorenzo Colittid593e292019-02-19 13:21:56 +09006123 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
6124 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08006125 cellLp.addLinkAddress(myIpv4);
6126 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6127 mCellNetworkAgent.sendLinkProperties(cellLp);
junyulai4a192e22018-06-13 15:00:37 +08006128 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09006129 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08006130 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006131
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006132 // As soon as stop is called, the linkproperties lose the stacked interface.
junyulai4a192e22018-06-13 15:00:37 +08006133 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
6134 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006135 LinkProperties expected = new LinkProperties(cellLp);
6136 expected.setNat64Prefix(kNat64Prefix);
6137 assertEquals(expected, actualLpAfterIpv4);
6138 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
junyulai4a192e22018-06-13 15:00:37 +08006139
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006140 // The interface removed callback happens but has no effect after stop is called.
6141 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6142 networkCallback.assertNoCallback();
6143
Lorenzo Colittid593e292019-02-19 13:21:56 +09006144 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006145 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006146 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006147 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006148
Lorenzo Colittid593e292019-02-19 13:21:56 +09006149 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6150 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6151 kNat64PrefixString, 96);
6152 networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
6153 mCellNetworkAgent);
6154
6155 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006156 cellLp.removeLinkAddress(myIpv4);
6157 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6158 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6159 mCellNetworkAgent.sendLinkProperties(cellLp);
6160 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006161 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006162 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6163 kNat64PrefixString, 96);
6164 networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006165 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6166
Lorenzo Colittid593e292019-02-19 13:21:56 +09006167
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006168 // Clat iface comes up. Expect stacked link to be added.
6169 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006170 networkCallback.expectLinkPropertiesLike(
6171 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006172 mCellNetworkAgent);
6173
6174 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006175 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6176 kNat64PrefixString, 96);
6177 networkCallback.expectLinkPropertiesLike(
6178 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006179 mCellNetworkAgent);
6180 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6181 networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
6182 mCellNetworkAgent);
6183
6184 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08006185 mCellNetworkAgent.disconnect();
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006186 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6187 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08006188 mCm.unregisterNetworkCallback(networkCallback);
6189 }
Chiachang Wanga6093042018-09-28 22:42:48 +08006190
6191 @Test
6192 public void testDataActivityTracking() throws RemoteException {
6193 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6194 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6195 .addCapability(NET_CAPABILITY_INTERNET)
6196 .build();
6197 mCm.registerNetworkCallback(networkRequest, networkCallback);
6198
6199 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6200 final LinkProperties cellLp = new LinkProperties();
6201 cellLp.setInterfaceName(MOBILE_IFNAME);
6202 mCellNetworkAgent.sendLinkProperties(cellLp);
6203 reset(mNetworkManagementService);
6204 mCellNetworkAgent.connect(true);
6205 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6206 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6207 eq(ConnectivityManager.TYPE_MOBILE));
6208
6209 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6210 final LinkProperties wifiLp = new LinkProperties();
6211 wifiLp.setInterfaceName(WIFI_IFNAME);
6212 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6213
6214 // Network switch
6215 reset(mNetworkManagementService);
6216 mWiFiNetworkAgent.connect(true);
6217 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6218 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6219 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6220 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6221 eq(ConnectivityManager.TYPE_WIFI));
6222 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6223
6224 // Disconnect wifi and switch back to cell
6225 reset(mNetworkManagementService);
6226 mWiFiNetworkAgent.disconnect();
6227 networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
6228 assertNoCallbacks(networkCallback);
6229 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6230 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6231 eq(ConnectivityManager.TYPE_MOBILE));
6232
6233 // reconnect wifi
6234 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6235 wifiLp.setInterfaceName(WIFI_IFNAME);
6236 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6237 mWiFiNetworkAgent.connect(true);
6238 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
6239 networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
6240 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6241
6242 // Disconnect cell
6243 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006244 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006245 mCellNetworkAgent.disconnect();
6246 networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
6247 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6248 // sent as network being switched. Ensure rule removal for cell will not be triggered
6249 // unexpectedly before network being removed.
6250 waitForIdle();
6251 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006252 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6253 verify(mMockDnsResolver, times(1))
Lorenzo Colittibc2aa342019-04-25 18:06:28 -07006254 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006255
6256 // Disconnect wifi
6257 ConditionVariable cv = waitForConnectivityBroadcasts(1);
6258 reset(mNetworkManagementService);
6259 mWiFiNetworkAgent.disconnect();
6260 waitFor(cv);
6261 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6262
6263 // Clean up
6264 mCm.unregisterNetworkCallback(networkCallback);
6265 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006266
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006267 private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006268 String[] values = tcpBufferSizes.split(",");
6269 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6270 String wmemValues = String.join(" ", values[3], values[4], values[5]);
6271 waitForIdle();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006272 try {
6273 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
6274 } catch (RemoteException e) {
6275 fail("mMockNetd should never throw RemoteException");
6276 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006277 reset(mMockNetd);
6278 }
6279
6280 @Test
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006281 public void testTcpBufferReset() {
6282 final String testTcpBufferSizes = "1,2,3,4,5,6";
6283
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006284 mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
6285 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006286 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006287 mCellNetworkAgent.connect(false);
6288 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6289
6290 // Change link Properties should have updated tcp buffer size.
6291 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006292 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006293 mCellNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006294 verifyTcpBufferSizeChange(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006295 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006296
6297 @Test
6298 public void testGetGlobalProxyForNetwork() {
6299 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6300 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6301 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6302 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6303 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6304 }
6305
6306 @Test
6307 public void testGetProxyForActiveNetwork() {
6308 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6309 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6310 mWiFiNetworkAgent.connect(true);
6311 waitForIdle();
6312 assertNull(mService.getProxyForNetwork(null));
6313
6314 final LinkProperties testLinkProperties = new LinkProperties();
6315 testLinkProperties.setHttpProxy(testProxyInfo);
6316
6317 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6318 waitForIdle();
6319
6320 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6321 }
6322
6323 @Test
6324 public void testGetProxyForVPN() {
6325 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6326
6327 // Set up a WiFi network with no proxy
6328 mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
6329 mWiFiNetworkAgent.connect(true);
6330 waitForIdle();
6331 assertNull(mService.getProxyForNetwork(null));
6332
6333 // Set up a VPN network with a proxy
6334 final int uid = Process.myUid();
6335 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
6336 final ArraySet<UidRange> ranges = new ArraySet<>();
6337 ranges.add(new UidRange(uid, uid));
6338 mMockVpn.setUids(ranges);
6339 LinkProperties testLinkProperties = new LinkProperties();
6340 testLinkProperties.setHttpProxy(testProxyInfo);
6341 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6342 waitForIdle();
6343
6344 // Connect to VPN with proxy
6345 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6346 vpnNetworkAgent.connect(true);
6347 mMockVpn.connect();
6348 waitForIdle();
6349
6350 // Test that the VPN network returns a proxy, and the WiFi does not.
6351 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6352 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6353 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6354
6355 // Test that the VPN network returns no proxy when it is set to null.
6356 testLinkProperties.setHttpProxy(null);
6357 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6358 waitForIdle();
6359 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6360 assertNull(mService.getProxyForNetwork(null));
6361
6362 // Set WiFi proxy and check that the vpn proxy is still null.
6363 testLinkProperties.setHttpProxy(testProxyInfo);
6364 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6365 waitForIdle();
6366 assertNull(mService.getProxyForNetwork(null));
6367
6368 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6369 // correct proxy setting.
6370 vpnNetworkAgent.disconnect();
6371 waitForIdle();
6372 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6373 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6374 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6375 }
Rubin Xu9a3f7242019-04-11 11:45:43 -07006376
6377 @Test
6378 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6379 LinkProperties lp = new LinkProperties();
6380 lp.setInterfaceName("tun0");
6381 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6382 // The uid range needs to cover the test app so the network is visible to it.
6383 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6384 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6385
6386 // Connected VPN should have interface rules set up. There are two expected invocations,
6387 // one during VPN uid update, one during VPN LinkProperties update
6388 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6389 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6390 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6391 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6392 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6393
6394 vpnNetworkAgent.disconnect();
6395 waitForIdle();
6396
6397 // Disconnected VPN should have interface rules removed
6398 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6399 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6400 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6401 }
6402
6403 @Test
6404 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6405 LinkProperties lp = new LinkProperties();
6406 lp.setInterfaceName("tun0");
6407 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6408 // The uid range needs to cover the test app so the network is visible to it.
6409 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6410 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6411
6412 // Legacy VPN should not have interface rules set up
6413 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6414 }
6415
Lorenzo Colittia6824cc2019-04-12 19:50:22 +09006416 @Test
Rubin Xu9a3f7242019-04-11 11:45:43 -07006417 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6418 throws Exception {
6419 LinkProperties lp = new LinkProperties();
6420 lp.setInterfaceName("tun0");
6421 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6422 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6423 // The uid range needs to cover the test app so the network is visible to it.
6424 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6425 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, Process.SYSTEM_UID, vpnRange);
6426
6427 // IPv6 unreachable route should not be misinterpreted as a default route
6428 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6429 }
6430
6431 @Test
6432 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6433 LinkProperties lp = new LinkProperties();
6434 lp.setInterfaceName("tun0");
6435 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6436 // The uid range needs to cover the test app so the network is visible to it.
6437 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6438 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
6439
6440 // Connected VPN should have interface rules set up. There are two expected invocations,
6441 // one during VPN uid update, one during VPN LinkProperties update
6442 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6443 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6444 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6445 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6446
6447 reset(mMockNetd);
6448 InOrder inOrder = inOrder(mMockNetd);
6449 lp.setInterfaceName("tun1");
6450 vpnNetworkAgent.sendLinkProperties(lp);
6451 waitForIdle();
6452 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6453 // removed first, then new rules added)
6454 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6455 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6456 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6457 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6458
6459 reset(mMockNetd);
6460 lp = new LinkProperties();
6461 lp.setInterfaceName("tun1");
6462 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6463 vpnNetworkAgent.sendLinkProperties(lp);
6464 waitForIdle();
6465 // VPN not routing everything should no longer have interface filtering rules
6466 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6467 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6468
6469 reset(mMockNetd);
6470 lp = new LinkProperties();
6471 lp.setInterfaceName("tun1");
6472 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6473 vpnNetworkAgent.sendLinkProperties(lp);
6474 waitForIdle();
6475 // Back to routing all IPv6 traffic should have filtering rules
6476 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6477 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6478 }
6479
6480 @Test
6481 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6482 LinkProperties lp = new LinkProperties();
6483 lp.setInterfaceName("tun0");
6484 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6485 // The uid range needs to cover the test app so the network is visible to it.
6486 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
6487 final MockNetworkAgent vpnNetworkAgent = establishVpn(lp, VPN_UID,
6488 Collections.singleton(vpnRange));
6489
6490 reset(mMockNetd);
6491 InOrder inOrder = inOrder(mMockNetd);
6492
6493 // Update to new range which is old range minus APP1, i.e. only APP2
6494 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6495 new UidRange(vpnRange.start, APP1_UID - 1),
6496 new UidRange(APP1_UID + 1, vpnRange.stop)));
6497 vpnNetworkAgent.setUids(newRanges);
6498 waitForIdle();
6499
6500 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6501 // Verify old rules are removed before new rules are added
6502 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6503 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6504 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6505 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6506 }
6507
6508
6509 private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
6510 Set<UidRange> vpnRange) {
6511 final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
6512 vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
6513 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6514 mMockVpn.connect();
6515 mMockVpn.setUids(vpnRange);
6516 vpnNetworkAgent.connect(true);
6517 waitForIdle();
6518 return vpnNetworkAgent;
6519 }
6520
6521 private void assertContainsExactly(int[] actual, int... expected) {
6522 int[] sortedActual = Arrays.copyOf(actual, actual.length);
6523 int[] sortedExpected = Arrays.copyOf(expected, expected.length);
6524 Arrays.sort(sortedActual);
6525 Arrays.sort(sortedExpected);
6526 assertArrayEquals(sortedExpected, sortedActual);
6527 }
6528
6529 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6530 final PackageInfo packageInfo = new PackageInfo();
6531 packageInfo.requestedPermissions = new String[0];
6532 packageInfo.applicationInfo = new ApplicationInfo();
6533 packageInfo.applicationInfo.privateFlags = 0;
6534 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6535 UserHandle.getAppId(uid));
6536 return packageInfo;
6537 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006538}