blob: 7ea9bcf36f915e612fc83779c9c48d6a1bf39402 [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
paulhu86e23eb2019-11-05 18:05:05 +080019import static android.Manifest.permission.CHANGE_NETWORK_STATE;
20import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
21import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
Rubin Xu9e64dc02019-04-23 18:04:14 +010022import static android.content.pm.PackageManager.GET_PERMISSIONS;
23import static android.content.pm.PackageManager.MATCH_ANY_USER;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090024import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
Erik Klinef851d6d2015-04-20 16:03:48 +090025import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Chalard Jean9ca13772019-11-15 12:08:36 +090026import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
27import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
28import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090029import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070030import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
31import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
32import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090033import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070034import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090035import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
36import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Chalard Jean9ca13772019-11-15 12:08:36 +090037import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070038import static android.net.ConnectivityManager.TYPE_WIFI;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080039import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
40import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
41import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
42import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
lucaslin783f2212019-10-22 18:27:33 +080043import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080044import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
45import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060046import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
47import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
48import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
52import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
53import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
54import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
55import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
57import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090058import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060059import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080060import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060061import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
62import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
63import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
64import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
65import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
66import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
67import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
68import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090069import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060070import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
71import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080072import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
73import static android.net.NetworkPolicyManager.RULE_NONE;
74import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
75import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000076import static android.net.RouteInfo.RTN_UNREACHABLE;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060077
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090078import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090079import static com.android.testutils.ConcurrentUtilsKt.await;
80import static com.android.testutils.ConcurrentUtilsKt.durationOf;
Chalard Jeane7b24752019-06-20 16:01:19 +090081import static com.android.testutils.ExceptionUtils.ignoreExceptions;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090082import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
83import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
84import static com.android.testutils.MiscAssertsKt.assertEmpty;
85import static com.android.testutils.MiscAssertsKt.assertLength;
86import static com.android.testutils.MiscAssertsKt.assertRunsInAtMost;
87import static com.android.testutils.MiscAssertsKt.assertThrows;
88
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090089import static org.junit.Assert.assertEquals;
90import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080091import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090092import static org.junit.Assert.assertNotNull;
93import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060094import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090095import static org.junit.Assert.fail;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090096import static org.mockito.ArgumentMatchers.anyLong;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090097import static org.mockito.ArgumentMatchers.anyString;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000098import static org.mockito.ArgumentMatchers.eq;
Erik Klinee89953b2018-01-11 16:11:10 +090099import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +0900100import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600101import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900102import static org.mockito.Mockito.doAnswer;
103import static org.mockito.Mockito.doNothing;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900104import static org.mockito.Mockito.doReturn;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000105import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -0800106import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600107import static org.mockito.Mockito.never;
108import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900109import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900110import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +0900111import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600112import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -0700113import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900114import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700115
junyulai7c469172019-01-16 20:23:34 +0800116import android.annotation.NonNull;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900117import android.app.AlarmManager;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900118import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400119import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400120import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900121import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900122import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700123import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400124import android.content.Intent;
125import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000126import android.content.pm.ApplicationInfo;
127import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100128import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000129import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900130import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400131import android.net.ConnectivityManager;
132import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900133import android.net.ConnectivityManager.PacketKeepalive;
134import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900135import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900136import android.net.ConnectivityThread;
Luke Huang65914772019-03-16 00:31:46 +0800137import android.net.IDnsResolver;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900138import android.net.IIpConnectivityMetrics;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800139import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900140import android.net.INetworkMonitor;
141import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800142import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700143import android.net.INetworkPolicyManager;
144import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800145import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900146import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800147import android.net.IpSecManager;
148import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900149import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700150import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700151import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400152import android.net.Network;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400153import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700154import android.net.NetworkFactory;
Chalard Jean9ca13772019-11-15 12:08:36 +0900155import android.net.NetworkInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400156import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700157import android.net.NetworkSpecifier;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900158import android.net.NetworkStack;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900159import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800160import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100161import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000162import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800163import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700164import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800165import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900166import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900167import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900168import android.net.shared.NetworkMonitorUtils;
169import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900170import android.net.util.MultinetworkPolicyTracker;
Chalard Jean751bb3f2019-06-19 23:29:58 +0900171import android.os.BadParcelableException;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100172import android.os.Binder;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900173import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400174import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700175import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700176import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700177import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900178import android.os.Looper;
Etan Cohena7434272017-04-03 12:17:51 -0700179import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800180import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700181import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000182import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800183import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900184import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900185import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000186import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900187import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800188import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900189import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800190import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100191import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700192import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800193import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700194
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800195import androidx.test.InstrumentationRegistry;
Guang Zhub90866d2019-09-01 21:37:04 -0700196import androidx.test.filters.FlakyTest;
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800197import androidx.test.filters.SmallTest;
198import androidx.test.runner.AndroidJUnit4;
199
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900200import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800201import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900202import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900203import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900204import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900205import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900206import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900207import com.android.server.connectivity.DefaultNetworkMetrics;
208import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900209import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800210import com.android.server.connectivity.Nat464Xlat;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900211import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000212import com.android.server.connectivity.ProxyTracker;
Mike Yuf9729752018-08-17 15:22:05 +0800213import com.android.server.connectivity.Tethering;
Chalard Jeandda156a2018-01-10 21:19:32 +0900214import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900215import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900216import com.android.server.net.NetworkPolicyManagerInternal;
Chalard Jeane7b24752019-06-20 16:01:19 +0900217import com.android.testutils.ExceptionUtils;
Chalard Jeance75e0e2019-05-28 16:48:32 +0900218import com.android.testutils.HandlerUtilsKt;
Chalard Jean059c4262019-09-30 17:51:12 +0900219import com.android.testutils.RecorderCallback.CallbackEntry;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900220import com.android.testutils.TestableNetworkCallback;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400221
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900222import org.junit.After;
223import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900224import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900225import org.junit.Test;
226import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900227import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000228import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900229import org.mockito.Mock;
230import org.mockito.MockitoAnnotations;
231import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900232import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900233
junyulai0c666972019-03-04 22:45:36 +0800234import java.io.IOException;
235import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800236import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000237import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700238import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900239import java.net.InetSocketAddress;
240import java.net.Socket;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400241import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900242import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100243import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800244import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500245import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100246import java.util.List;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100247import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900248import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800249import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800250import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800251import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900252import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900253import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700254import java.util.concurrent.atomic.AtomicBoolean;
Chalard Jean9ca13772019-11-15 12:08:36 +0900255import java.util.function.Predicate;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900256
257import kotlin.reflect.KClass;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700258
259/**
260 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400261 *
262 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900263 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700264 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900265@RunWith(AndroidJUnit4.class)
266@SmallTest
267public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700268 private static final String TAG = "ConnectivityServiceTest";
269
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900270 private static final int TIMEOUT_MS = 500;
Chalard Jeanb299b842019-09-27 17:13:14 +0900271 private static final int TEST_LINGER_DELAY_MS = 300;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900272 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
273 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
274 // timeout. For this, our assertions should run fast enough to leave less than
275 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
276 // supposedly fired, and the time we call expectCallback.
Chalard Jeanb299b842019-09-27 17:13:14 +0900277 private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900278 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
279 // complete before callbacks are verified.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900280 private static final int TEST_REQUEST_TIMEOUT_MS = 150;
281
282 private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900283
junyulai4a192e22018-06-13 15:00:37 +0800284 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700285 private static final String MOBILE_IFNAME = "test_rmnet_data0";
286 private static final String WIFI_IFNAME = "test_wlan0";
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200287 private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
Luke Huang65914772019-03-16 00:31:46 +0800288 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700289
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900290 private MockContext mServiceContext;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900291 private HandlerThread mCsHandlerThread;
292 private ConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900293 private WrappedConnectivityManager mCm;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900294 private TestNetworkAgentWrapper mWiFiNetworkAgent;
295 private TestNetworkAgentWrapper mCellNetworkAgent;
296 private TestNetworkAgentWrapper mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900297 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900298 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800299 private INetworkPolicyListener mPolicyListener;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900300 private WrappedMultinetworkPolicyTracker mPolicyTracker;
301 private HandlerThread mAlarmManagerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700302
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900303 @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
Hugo Benichi64901e52017-10-19 14:42:40 +0900304 @Mock IpConnectivityMetrics.Logger mMetricsService;
305 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900306 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600307 @Mock INetworkStatsService mStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800308 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800309 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800310 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900311 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100312 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000313 @Mock UserManager mUserManager;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900314 @Mock NotificationManager mNotificationManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900315 @Mock AlarmManager mAlarmManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900316
waynema13516842019-03-12 18:13:49 +0800317 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
318 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900319
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900320 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
321 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
322 // reflect the state of our test ConnectivityService.
323 private class WrappedConnectivityManager extends ConnectivityManager {
324 private Network mFakeBoundNetwork;
325
326 public synchronized boolean bindProcessToNetwork(Network network) {
327 mFakeBoundNetwork = network;
328 return true;
329 }
330
331 public synchronized Network getBoundNetworkForProcess() {
332 return mFakeBoundNetwork;
333 }
334
335 public WrappedConnectivityManager(Context context, ConnectivityService service) {
336 super(context, service);
337 }
338 }
339
Paul Jensend7b6ca92015-05-13 14:05:12 -0400340 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900341 private final MockContentResolver mContentResolver;
Chalard Jean9ca13772019-11-15 12:08:36 +0900342 // Contains all registered receivers since this object was created. Useful to clear
343 // them when needed, as BroadcastInterceptingContext does not provide this facility.
344 private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>();
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900345
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900346 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900347 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900348
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900349 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400350 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900351
352 mResources = spy(base.getResources());
353 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
354 thenReturn(new String[] {
355 "wifi,1,1,1,-1,true",
356 "mobile,0,0,0,-1,true",
357 "mobile_mms,2,0,2,60000,true",
Chalard Jean9ca13772019-11-15 12:08:36 +0900358 "mobile_supl,3,0,2,60000,true",
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900359 });
360
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200361 when(mResources.getStringArray(
362 com.android.internal.R.array.config_wakeonlan_supported_interfaces))
363 .thenReturn(new String[]{
364 WIFI_WOL_IFNAME,
365 });
366
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900367 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900368 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400369 }
370
371 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900372 public void startActivityAsUser(Intent intent, UserHandle handle) {
373 mStartedActivities.offer(intent);
374 }
375
Chalard Jeanf30d1e12019-06-27 08:24:51 +0000376 public Intent expectStartActivityIntent(int timeoutMs) {
377 Intent intent = null;
378 try {
379 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
380 } catch (InterruptedException e) {}
381 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
382 return intent;
383 }
384
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900385 public void expectNoStartActivityIntent(int timeoutMs) {
386 try {
387 assertNull("Received unexpected Intent to start activity",
388 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
389 } catch (InterruptedException e) {}
390 }
391
392 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900393 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900394 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900395 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900396 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000397 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900398 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400399 return super.getSystemService(name);
400 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900401
402 @Override
403 public ContentResolver getContentResolver() {
404 return mContentResolver;
405 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900406
407 @Override
408 public Resources getResources() {
409 return mResources;
410 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100411
412 @Override
413 public PackageManager getPackageManager() {
414 return mPackageManager;
415 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900416
417 @Override
418 public void enforceCallingOrSelfPermission(String permission, String message) {
419 // The mainline permission can only be held if signed with the network stack certificate
420 // Skip testing for this permission.
421 if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
422 // All other permissions should be held by the test or unnecessary: check as normal to
423 // make sure the code does not rely on unexpected permissions.
424 super.enforceCallingOrSelfPermission(permission, message);
425 }
Chalard Jean9ca13772019-11-15 12:08:36 +0900426
427 @Override
428 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
429 mRegisteredReceivers.add(receiver);
430 return super.registerReceiver(receiver, filter);
431 }
432
433 public void clearRegisteredReceivers() {
434 // super.unregisterReceiver is a no-op for receivers that are not registered (because
435 // they haven't been registered or because they have already been unregistered).
436 // For the same reason, don't bother clearing mRegisteredReceivers.
437 for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv);
438 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900439 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400440
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900441 private void waitForIdle() {
442 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
443 waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
444 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
445 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
446 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
447 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Hugo Benichibb91c572017-05-22 10:44:02 +0900448 }
449
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900450 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900451 if (agent == null) {
452 return;
453 }
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900454 agent.waitForIdle(timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900455 }
456
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900457 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +0900458 public void testWaitForIdle() throws Exception {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900459 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
460
461 // Tests that waitForIdle returns immediately if the service is already idle.
462 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900463 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900464 }
465
466 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900467 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900468 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900469 mWiFiNetworkAgent.connect(false);
470 waitFor(cv);
471 Network n = mWiFiNetworkAgent.getNetwork();
472 assertNotNull(n);
473
474 // Tests that calling waitForIdle waits for messages to be processed.
475 for (int i = 0; i < attempts; i++) {
476 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900477 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900478 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
479 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900480 }
481
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900482 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
483 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800484 @Ignore
Chalard Jeane7b24752019-06-20 16:01:19 +0900485 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900486 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900487 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900488 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Hugo Benichi5d540d12016-10-17 15:54:51 +0900489 mWiFiNetworkAgent.connect(false);
490 waitFor(cv);
491 Network n = mWiFiNetworkAgent.getNetwork();
492 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900493
494 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900495 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900496 for (int i = 0; i < attempts; i++) {
497 mWiFiNetworkAgent.setSignalStrength(i);
498 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
499 // We hit a race condition, as expected. Pass the test.
500 return;
501 }
502 }
503
504 // No race? There is a bug in this test.
505 fail("expected race condition at least once in " + attempts + " attempts");
506 }
507
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900508 private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800509 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
510 | NETWORK_VALIDATION_PROBE_HTTP
511 | NETWORK_VALIDATION_PROBE_HTTPS;
512 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
513 | NETWORK_VALIDATION_RESULT_VALID;
514 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
515 | NETWORK_VALIDATION_PROBE_FALLBACK
516 | NETWORK_VALIDATION_RESULT_PARTIAL;
517 private static final int VALIDATION_RESULT_INVALID = 0;
518
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900519 private INetworkMonitor mNetworkMonitor;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900520 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800521 private int mNmValidationResult = VALIDATION_RESULT_BASE;
lucaslin783f2212019-10-22 18:27:33 +0800522 private int mProbesCompleted;
523 private int mProbesSucceeded;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900524 private String mNmValidationRedirectUrl = null;
525 private boolean mNmProvNotificationRequested = false;
526
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900527 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
528 // Contains the redirectUrl from networkStatus(). Before reading, wait for
529 // mNetworkStatusReceived.
530 private String mRedirectUrl;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900531
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900532 TestNetworkAgentWrapper(int transport) throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100533 this(transport, new LinkProperties());
534 }
535
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900536 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
537 throws Exception {
538 super(transport, linkProperties, mServiceContext);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900539
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900540 // Waits for the NetworkAgent to be registered, which includes the creation of the
541 // NetworkMonitor.
542 waitForIdle(TIMEOUT_MS);
Chalard Jean3da8e0f2019-09-20 17:19:31 +0900543 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
544 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900545 }
546
547 @Override
548 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
549 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900550 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900551
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900552 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900553 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900554 return null;
555 };
556
Chalard Jeane7b24752019-06-20 16:01:19 +0900557 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
558 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900559
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900560 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900561 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
562 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
563 doNothing().when(mNetworkStack).makeNetworkMonitor(
564 nmNetworkCaptor.capture(),
565 any() /* name */,
566 nmCbCaptor.capture());
567
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900568 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400569 @Override
570 public void networkStatus(int status, String redirectUrl) {
571 mRedirectUrl = redirectUrl;
572 mNetworkStatusReceived.open();
573 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400574 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900575
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900576 assertEquals(na.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900577 mNmCallbacks = nmCbCaptor.getValue();
578
Chalard Jeane7b24752019-06-20 16:01:19 +0900579 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900580
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900581 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900582 }
583
Chalard Jeane7b24752019-06-20 16:01:19 +0900584 private void onValidationRequested() throws Exception {
585 if (mNmProvNotificationRequested
586 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
587 mNmCallbacks.hideProvisioningNotification();
588 mNmProvNotificationRequested = false;
589 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900590
lucaslin783f2212019-10-22 18:27:33 +0800591 mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
Chalard Jeane7b24752019-06-20 16:01:19 +0900592 mNmCallbacks.notifyNetworkTested(
593 mNmValidationResult, mNmValidationRedirectUrl);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900594
Chalard Jeane7b24752019-06-20 16:01:19 +0900595 if (mNmValidationRedirectUrl != null) {
596 mNmCallbacks.showProvisioningNotification(
597 "test_provisioning_notif_action", "com.android.test.package");
598 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900599 }
Paul Jensen3d911462015-06-12 06:40:24 -0400600 }
601
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900602 /**
603 * Connect without adding any internet capability.
604 */
Paul Jensene0988542015-06-25 15:30:08 -0400605 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900606 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400607 }
608
Paul Jensend7b6ca92015-05-13 14:05:12 -0400609 /**
Paul Jensene0988542015-06-25 15:30:08 -0400610 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400611 * @param validated Indicate if network should pretend to be validated.
612 */
613 public void connect(boolean validated) {
lucaslin783f2212019-10-22 18:27:33 +0800614 connect(validated, true, false /* isStrictMode */);
Hugo Benichi16f0a942017-06-20 14:07:59 +0900615 }
616
617 /**
618 * Transition this NetworkAgent to CONNECTED state.
619 * @param validated Indicate if network should pretend to be validated.
620 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
621 */
lucaslin783f2212019-10-22 18:27:33 +0800622 public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900623 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400624
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900625 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400626 final ConditionVariable validatedCv = new ConditionVariable();
627 if (validated) {
lucaslin783f2212019-10-22 18:27:33 +0800628 setNetworkValid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400629 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900630 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900631 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400632 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900633 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400634 public void onCapabilitiesChanged(Network network,
635 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400636 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900637 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400638 validatedCv.open();
639 }
640 }
641 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400642 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400643 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900644 if (hasInternet) {
645 addCapability(NET_CAPABILITY_INTERNET);
646 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400647
Paul Jensene0988542015-06-25 15:30:08 -0400648 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400649
650 if (validated) {
651 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400652 waitFor(validatedCv);
lucaslin783f2212019-10-22 18:27:33 +0800653 setNetworkInvalid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400654 }
655
656 if (callback != null) mCm.unregisterNetworkCallback(callback);
657 }
658
lucaslin783f2212019-10-22 18:27:33 +0800659 public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
660 setNetworkPortal(redirectUrl, isStrictMode);
661 connect(false, true /* hasInternet */, isStrictMode);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400662 }
663
lucasline252a742019-03-12 13:08:03 +0800664 public void connectWithPartialConnectivity() {
665 setNetworkPartial();
666 connect(false);
667 }
668
lucaslin783f2212019-10-22 18:27:33 +0800669 public void connectWithPartialValidConnectivity(boolean isStrictMode) {
670 setNetworkPartialValid(isStrictMode);
671 connect(false, true /* hasInternet */, isStrictMode);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900672 }
673
lucaslin783f2212019-10-22 18:27:33 +0800674 void setNetworkValid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900675 mNmValidationResult = VALIDATION_RESULT_VALID;
676 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800677 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP;
678 if (isStrictMode) {
679 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
680 }
681 // The probesCompleted equals to probesSucceeded for the case of valid network, so put
682 // the same value into two different parameter of the method.
683 setProbesStatus(probesSucceeded, probesSucceeded);
Erik Kline1d3db322017-02-28 16:20:20 +0900684 }
685
lucaslin783f2212019-10-22 18:27:33 +0800686 void setNetworkInvalid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900687 mNmValidationResult = VALIDATION_RESULT_INVALID;
688 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800689 int probesCompleted = VALIDATION_RESULT_BASE;
690 int probesSucceeded = VALIDATION_RESULT_INVALID;
691 // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
692 // tried to validate the private DNS but failed.
693 if (isStrictMode) {
694 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
695 probesSucceeded = probesCompleted;
696 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
697 }
698 setProbesStatus(probesCompleted, probesSucceeded);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900699 }
700
lucaslin783f2212019-10-22 18:27:33 +0800701 void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
702 setNetworkInvalid(isStrictMode);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900703 mNmValidationRedirectUrl = redirectUrl;
lucaslin783f2212019-10-22 18:27:33 +0800704 // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
705 // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
706 int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
707 int probesSucceeded = VALIDATION_RESULT_INVALID;
708 if (isStrictMode) {
709 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
710 }
711 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400712 }
713
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900714 void setNetworkPartial() {
715 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
716 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800717 int probesCompleted = VALIDATION_RESULT_BASE;
718 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
719 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400720 }
Paul Jensene0988542015-06-25 15:30:08 -0400721
lucaslin783f2212019-10-22 18:27:33 +0800722 void setNetworkPartialValid(boolean isStrictMode) {
723 setNetworkPartial();
724 mNmValidationResult |= VALIDATION_RESULT_VALID;
725 int probesCompleted = VALIDATION_RESULT_BASE;
726 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
727 // Suppose the partial network cannot pass the private DNS validation as well, so only
728 // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
729 if (isStrictMode) {
730 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
731 }
732 setProbesStatus(probesCompleted, probesSucceeded);
733 }
734
735 void setProbesStatus(int probesCompleted, int probesSucceeded) {
736 mProbesCompleted = probesCompleted;
737 mProbesSucceeded = probesSucceeded;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900738 }
Paul Jensen232437312016-04-06 09:51:26 -0400739
740 public String waitForRedirectUrl() {
741 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
742 return mRedirectUrl;
743 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900744
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900745 public void expectDisconnected() {
746 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900747 }
748
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900749 public void expectPreventReconnectReceived() {
750 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900751 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400752 }
753
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900754 /**
755 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
756 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900757 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900758 * expectRemoveRequests.
759 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700760 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400761 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
762 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400763 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700764
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900765 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900766 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
767 // once, then cause some other thread to add or remove requests, then call
768 // waitForRequests().
769 // It is not possible to wait for both add and remove requests. When adding, the queue
770 // contains the expected score. When removing, the value is unused, all matters is the
771 // number of objects in the queue.
772 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900773
774 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900775 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900776 private boolean mExpectingAdditions;
777
Etan Cohenddb720a2019-01-08 12:09:18 -0800778 // Used to collect the networks requests managed by this factory. This is a duplicate of
779 // the internal information stored in the NetworkFactory (which is private).
780 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
781
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700782 public MockNetworkFactory(Looper looper, Context context, String logTag,
783 NetworkCapabilities filter) {
784 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900785 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700786 }
787
788 public int getMyRequestCount() {
789 return getRequestCount();
790 }
791
792 protected void startNetwork() {
793 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400794 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700795 }
796
797 protected void stopNetwork() {
798 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400799 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700800 }
801
802 public boolean getMyStartRequested() {
803 return mNetworkStarted.get();
804 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400805
806 public ConditionVariable getNetworkStartedCV() {
807 mNetworkStartedCV.close();
808 return mNetworkStartedCV;
809 }
810
811 public ConditionVariable getNetworkStoppedCV() {
812 mNetworkStoppedCV.close();
813 return mNetworkStoppedCV;
814 }
815
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900816 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900817 protected void handleAddRequest(NetworkRequest request, int score,
818 int factorySerialNumber) {
819 synchronized (mExpectations) {
820 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900821
Chalard Jean05ab6812018-05-02 21:14:54 +0900822 assertNotNull("Added more requests than expected (" + request + " score : "
823 + score + ")", expectedScore);
824 // If we're expecting anything, we must be expecting additions.
825 if (!mExpectingAdditions) {
826 fail("Can't add requests while expecting requests to be removed");
827 }
828 if (expectedScore != score) {
829 fail("Expected score was " + expectedScore + " but actual was " + score
830 + " in added request");
831 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900832
Chalard Jean05ab6812018-05-02 21:14:54 +0900833 // Add the request.
834 mNetworkRequests.put(request.requestId, request);
835 super.handleAddRequest(request, score, factorySerialNumber);
836 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900837 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400838 }
839
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900840 @Override
841 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900842 synchronized (mExpectations) {
843 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900844
Chalard Jean05ab6812018-05-02 21:14:54 +0900845 assertTrue("Removed more requests than expected", expectedScore != null);
846 // If we're expecting anything, we must be expecting removals.
847 if (mExpectingAdditions) {
848 fail("Can't remove requests while expecting requests to be added");
849 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900850
Chalard Jean05ab6812018-05-02 21:14:54 +0900851 // Remove the request.
852 mNetworkRequests.remove(request.requestId);
853 super.handleRemoveRequest(request);
854 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900855 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400856 }
857
Etan Cohenddb720a2019-01-08 12:09:18 -0800858 // Trigger releasing the request as unfulfillable
859 public void triggerUnfulfillable(NetworkRequest r) {
860 super.releaseRequestAsUnfulfillableByAnyFactory(r);
861 }
862
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900863 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900864 if (mExpectations.size() != 0) {
865 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900866 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400867 }
868
Chalard Jean05ab6812018-05-02 21:14:54 +0900869 // Expects that requests with the specified scores will be added.
870 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900871 assertNoExpectations();
872 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900873 for (int score : scores) {
874 mExpectations.add(score);
875 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400876 }
877
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900878 // Expects that count requests will be removed.
879 public void expectRemoveRequests(final int count) {
880 assertNoExpectations();
881 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900882 for (int i = 0; i < count; ++i) {
883 mExpectations.add(0); // For removals the score is ignored so any value will do.
884 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900885 }
886
887 // Waits for the expected request additions or removals to happen within a timeout.
888 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900889 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
890 synchronized (mExpectations) {
891 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
892 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
893 }
894 }
895 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900896 final String msg = count + " requests still not " +
897 (mExpectingAdditions ? "added" : "removed") +
898 " after " + TIMEOUT_MS + " ms";
899 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900900 }
901
Etan Cohenddb720a2019-01-08 12:09:18 -0800902 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
903 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900904 waitForRequests();
905 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800906 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400907 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700908 }
909
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900910 private static Looper startHandlerThreadAndReturnLooper() {
911 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
912 handlerThread.start();
913 return handlerThread.getLooper();
914 }
915
916 private class MockVpn extends Vpn {
917 // TODO : the interactions between this mock and the mock network agent are too
918 // hard to get right at this moment, because it's unclear in which case which
919 // target needs to get a method call or both, and in what order. It's because
920 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
921 // parent class of MockVpn agent wants that responsibility.
922 // That being said inside the test it should be possible to make the interactions
923 // harder to get wrong with precise speccing, judicious comments, helper methods
924 // and a few sprinkled assertions.
925
926 private boolean mConnected = false;
927 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
928 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900929 private TestNetworkAgentWrapper mMockNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900930
931 public MockVpn(int userId) {
932 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
933 userId);
934 }
935
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900936 public void setNetworkAgent(TestNetworkAgentWrapper agent) {
937 agent.waitForIdle(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900938 mMockNetworkAgent = agent;
939 mNetworkAgent = agent.getNetworkAgent();
940 mNetworkCapabilities.set(agent.getNetworkCapabilities());
941 }
942
943 public void setUids(Set<UidRange> uids) {
944 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800945 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900946 }
947
948 @Override
949 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800950 if (mMockNetworkAgent == null) {
951 return NETID_UNSET;
952 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900953 return mMockNetworkAgent.getNetwork().netId;
954 }
955
956 @Override
957 public boolean appliesToUid(int uid) {
958 return mConnected; // Trickery to simplify testing.
959 }
960
961 @Override
962 protected boolean isCallerEstablishedOwnerLocked() {
963 return mConnected; // Similar trickery
964 }
965
Varun Anandc51b06d2019-02-25 17:22:02 -0800966 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900967 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
968 mConnected = true;
969 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -0800970 mConfig.isMetered = isAlwaysMetered;
971 }
972
973 public void connectAsAlwaysMetered() {
974 connect(true /* isAlwaysMetered */);
975 }
976
977 public void connect() {
978 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900979 }
980
981 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -0800982 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
983 if (!mConnected) return null;
984 super.updateCapabilities(defaultNetwork);
985 // Because super.updateCapabilities will update the capabilities of the agent but
986 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900987 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -0800988 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900989 }
990
991 private void copyCapabilitiesToNetworkAgent() {
992 if (null != mMockNetworkAgent) {
993 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
994 false /* sendToConnectivityService */);
995 }
996 }
997
998 public void disconnect() {
999 mConnected = false;
1000 mConfig = null;
1001 }
1002 }
1003
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001004 private void mockVpn(int uid) {
1005 synchronized (mService.mVpns) {
1006 int userId = UserHandle.getUserId(uid);
1007 mMockVpn = new MockVpn(userId);
1008 // This has no effect unless the VPN is actually connected, because things like
1009 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1010 // netId, and check if that network is actually connected.
1011 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001012 }
1013 }
1014
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001015 private void setUidRulesChanged(int uidRules) throws RemoteException {
1016 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1017 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001018
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001019 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
1020 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1021 }
1022
1023 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1024 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1025 }
1026
1027 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1028 volatile boolean mConfigRestrictsAvoidBadWifi;
1029 volatile int mConfigMeteredMultipathPreference;
1030
1031 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001032 super(c, h, r);
1033 }
1034
1035 @Override
1036 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001037 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +09001038 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001039
1040 @Override
1041 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001042 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +08001043 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001044 }
1045
Paul Jensen3d911462015-06-12 06:40:24 -04001046 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001047 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1048 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001049 */
1050 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001051 if (conditionVariable.block(TIMEOUT_MS)) {
1052 return;
1053 }
1054 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001055 }
1056
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001057 private static final int VPN_USER = 0;
1058 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1059 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1060 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1061
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001062 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001063 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001064 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001065
Hugo Benichi64901e52017-10-19 14:42:40 +09001066 MockitoAnnotations.initMocks(this);
1067 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1068
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001069 when(mUserManager.getUsers(eq(true))).thenReturn(
1070 Arrays.asList(new UserInfo[] {
1071 new UserInfo(VPN_USER, "", 0),
1072 }));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001073
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001074 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1075 // http://b/25897652 .
1076 if (Looper.myLooper() == null) {
1077 Looper.prepare();
1078 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001079 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001080
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001081 FakeSettingsProvider.clearSettingsProvider();
1082 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1083 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001084 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1085 LocalServices.addService(
1086 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001087
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001088 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1089 mAlarmManagerThread.start();
1090 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1091
1092 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1093 final ConnectivityService.Dependencies deps = makeDependencies();
1094 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001095 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001096 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001097 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001098 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001099 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001100 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001101 deps);
1102 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1103 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001104
Mike Yuf9729752018-08-17 15:22:05 +08001105 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1106 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1107 verify(mNpm).registerListener(policyListenerCaptor.capture());
1108 mPolicyListener = policyListenerCaptor.getValue();
1109
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001110 // Create local CM before sending system ready so that we can answer
1111 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001112 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001113 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001114 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001115 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001116
1117 // Ensure that the default setting for Captive Portals is used for most tests
1118 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001119 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001120 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001121 }
1122
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001123 private ConnectivityService.Dependencies makeDependencies() {
1124 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1125 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1126 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1127
1128 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1129 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1130 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
1131 doReturn(mNetworkStack).when(deps).getNetworkStack();
1132 doReturn(systemProperties).when(deps).getSystemProperties();
1133 doReturn(mock(Tethering.class)).when(deps).makeTethering(any(), any(), any(), any(), any());
1134 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1135 doReturn(mMetricsService).when(deps).getMetricsLogger();
1136 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1137 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
1138 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1139 doAnswer(inv -> {
1140 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1141 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1142 return mPolicyTracker;
1143 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1144
1145 return deps;
1146 }
1147
1148 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1149 doAnswer(inv -> {
1150 final long when = inv.getArgument(1);
1151 final WakeupMessage wakeupMsg = inv.getArgument(3);
1152 final Handler handler = inv.getArgument(4);
1153
1154 long delayMs = when - SystemClock.elapsedRealtime();
1155 if (delayMs < 0) delayMs = 0;
1156 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1157 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1158 + "ms into the future: " + delayMs);
1159 }
1160 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1161 delayMs);
1162
1163 return null;
1164 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1165 any(WakeupMessage.class), any());
1166
1167 doAnswer(inv -> {
1168 final WakeupMessage wakeupMsg = inv.getArgument(0);
1169 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1170 return null;
1171 }).when(am).cancel(any(WakeupMessage.class));
1172 }
1173
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001174 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001175 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001176 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001177 if (mCellNetworkAgent != null) {
1178 mCellNetworkAgent.disconnect();
1179 mCellNetworkAgent = null;
1180 }
1181 if (mWiFiNetworkAgent != null) {
1182 mWiFiNetworkAgent.disconnect();
1183 mWiFiNetworkAgent = null;
1184 }
1185 if (mEthernetNetworkAgent != null) {
1186 mEthernetNetworkAgent.disconnect();
1187 mEthernetNetworkAgent = null;
1188 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001189 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001190
1191 mCsHandlerThread.quitSafely();
1192 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001193 }
1194
Rubin Xu9e64dc02019-04-23 18:04:14 +01001195 private void mockDefaultPackages() throws Exception {
1196 final String testPackageName = mContext.getPackageName();
1197 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1198 testPackageName, PackageManager.GET_PERMISSIONS);
1199 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1200 new String[] {testPackageName});
1201 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1202 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1203
1204 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1205 Arrays.asList(new PackageInfo[] {
1206 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1207 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1208 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1209 }));
1210 }
1211
Paul Jensend7b6ca92015-05-13 14:05:12 -04001212 private void verifyActiveNetwork(int transport) {
1213 // Test getActiveNetworkInfo()
1214 assertNotNull(mCm.getActiveNetworkInfo());
1215 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1216 // Test getActiveNetwork()
1217 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001218 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001219 if (!NetworkCapabilities.isValidTransport(transport)) {
1220 throw new IllegalStateException("Unknown transport " + transport);
1221 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001222 switch (transport) {
1223 case TRANSPORT_WIFI:
1224 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1225 break;
1226 case TRANSPORT_CELLULAR:
1227 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1228 break;
1229 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001230 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001231 }
1232 // Test getNetworkInfo(Network)
1233 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001234 assertEquals(transportToLegacyType(transport),
1235 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001236 // Test getNetworkCapabilities(Network)
1237 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1238 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1239 }
1240
1241 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001242 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001243 // Test getActiveNetworkInfo()
1244 assertNull(mCm.getActiveNetworkInfo());
1245 // Test getActiveNetwork()
1246 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001247 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001248 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001249 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001250 }
1251
1252 /**
1253 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1254 * broadcasts are received.
1255 */
Chalard Jean407deb72019-11-19 16:14:30 +09001256 private ConditionVariable registerConnectivityBroadcast(final int count) {
1257 return registerConnectivityBroadcastThat(count, intent -> true);
Chalard Jean9ca13772019-11-15 12:08:36 +09001258 }
1259
Chalard Jean407deb72019-11-19 16:14:30 +09001260 private ConditionVariable registerConnectivityBroadcastThat(final int count,
Chalard Jean9ca13772019-11-15 12:08:36 +09001261 @NonNull final Predicate<Intent> filter) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001262 final ConditionVariable cv = new ConditionVariable();
Chalard Jean9ca13772019-11-15 12:08:36 +09001263 final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
1264 intentFilter.addAction(CONNECTIVITY_ACTION_SUPL);
1265 final BroadcastReceiver receiver = new BroadcastReceiver() {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001266 private int remaining = count;
1267 public void onReceive(Context context, Intent intent) {
Chalard Jean9ca13772019-11-15 12:08:36 +09001268 if (!filter.test(intent)) return;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001269 if (--remaining == 0) {
1270 cv.open();
1271 mServiceContext.unregisterReceiver(this);
1272 }
1273 }
Chalard Jean9ca13772019-11-15 12:08:36 +09001274 };
1275 mServiceContext.registerReceiver(receiver, intentFilter);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001276 return cv;
1277 }
1278
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001279 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001280 public void testNetworkTypes() {
1281 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1282 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1283 // will fail. Failing here is much easier to debug.
1284 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1285 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001286 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1287 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1288
1289 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1290 // mocks, this assert exercises the ConnectivityService code path that ensures that
1291 // TYPE_ETHERNET is supported if the ethernet service is running.
1292 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001293 }
1294
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001295 @Test
Chalard Jean9ca13772019-11-15 12:08:36 +09001296 public void testNetworkFeature() throws Exception {
1297 // Connect the cell agent and wait for the connected broadcast.
1298 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1299 mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
Chalard Jean407deb72019-11-19 16:14:30 +09001300 final ConditionVariable cv1 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001301 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE);
1302 mCellNetworkAgent.connect(true);
1303 waitFor(cv1);
1304
1305 // Build legacy request for SUPL.
1306 final NetworkCapabilities legacyCaps = new NetworkCapabilities();
1307 legacyCaps.addTransportType(TRANSPORT_CELLULAR);
1308 legacyCaps.addCapability(NET_CAPABILITY_SUPL);
1309 final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
1310 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
1311
1312 // Send request and check that the legacy broadcast for SUPL is sent correctly.
1313 final TestNetworkCallback callback = new TestNetworkCallback();
Chalard Jean407deb72019-11-19 16:14:30 +09001314 final ConditionVariable cv2 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001315 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1316 mCm.requestNetwork(legacyRequest, callback);
1317 callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1318 waitFor(cv2);
1319
1320 // File another request, withdraw it and make sure no broadcast is sent
Chalard Jean407deb72019-11-19 16:14:30 +09001321 final ConditionVariable cv3 = registerConnectivityBroadcast(1);
Chalard Jean9ca13772019-11-15 12:08:36 +09001322 final TestNetworkCallback callback2 = new TestNetworkCallback();
1323 mCm.requestNetwork(legacyRequest, callback2);
1324 callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1325 mCm.unregisterNetworkCallback(callback2);
1326 assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent
1327 // As the broadcast did not fire, the receiver was not unregistered. Do this now.
1328 mServiceContext.clearRegisteredReceivers();
1329
1330 // Withdraw the request and check that the broadcast for disconnection is sent.
Chalard Jean407deb72019-11-19 16:14:30 +09001331 final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent ->
Chalard Jean9ca13772019-11-15 12:08:36 +09001332 !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected()
1333 && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1334 mCm.unregisterNetworkCallback(callback);
1335 waitFor(cv4);
1336
1337 // Re-file the request and expect the connected broadcast again
Chalard Jean407deb72019-11-19 16:14:30 +09001338 final ConditionVariable cv5 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001339 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1340 final TestNetworkCallback callback3 = new TestNetworkCallback();
1341 mCm.requestNetwork(legacyRequest, callback3);
1342 callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1343 waitFor(cv5);
1344
1345 // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one
1346 // for mobile. Use a small hack to check that both have been sent, but the order is
1347 // not contractual.
1348 final AtomicBoolean vanillaAction = new AtomicBoolean(false);
1349 final AtomicBoolean suplAction = new AtomicBoolean(false);
Chalard Jean407deb72019-11-19 16:14:30 +09001350 final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> {
Chalard Jean9ca13772019-11-15 12:08:36 +09001351 if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
1352 vanillaAction.set(true);
1353 } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) {
1354 suplAction.set(true);
1355 }
1356 return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
1357 });
1358 mCellNetworkAgent.disconnect();
1359 waitFor(cv6);
1360 assertTrue(vanillaAction.get());
1361 assertTrue(suplAction.get());
1362 }
1363
1364 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001365 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001366 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001367 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1368 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001369 assertNull(mCm.getActiveNetworkInfo());
1370 assertNull(mCm.getActiveNetwork());
1371 // Test bringing up validated cellular.
Chalard Jean407deb72019-11-19 16:14:30 +09001372 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001373 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001374 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001375 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001376 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001377 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1378 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1379 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1380 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1381 // Test bringing up validated WiFi.
Chalard Jean407deb72019-11-19 16:14:30 +09001382 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001383 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001384 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001385 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001386 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001387 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1388 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1389 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1390 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1391 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001392 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001393 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001394 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001395 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001396 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001397 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1398 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001399 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001400 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001401 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001402 verifyNoNetwork();
1403 }
1404
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001405 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001406 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1407 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001408 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001409 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001410 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001411 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001412 verifyActiveNetwork(TRANSPORT_WIFI);
1413 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001414 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001415 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001416 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001417 verifyActiveNetwork(TRANSPORT_WIFI);
1418 // Test cellular disconnect.
1419 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001420 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001421 verifyActiveNetwork(TRANSPORT_WIFI);
1422 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001423 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001424 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001425 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001426 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001427 verifyActiveNetwork(TRANSPORT_CELLULAR);
1428 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001429 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001430 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001431 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001432 verifyActiveNetwork(TRANSPORT_WIFI);
1433 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001434 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001435 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001436 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001437 verifyNoNetwork();
1438 }
1439
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001440 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001441 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1442 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001443 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001444 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001445 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001446 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001447 verifyActiveNetwork(TRANSPORT_CELLULAR);
1448 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001449 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001450 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001451 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001452 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001453 verifyActiveNetwork(TRANSPORT_WIFI);
1454 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001455 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001456 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001457 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001458 verifyActiveNetwork(TRANSPORT_CELLULAR);
1459 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001460 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001461 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001462 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001463 verifyNoNetwork();
1464 }
1465
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001466 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001467 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001468 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001469 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001470 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001471 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001472 waitFor(cv);
1473 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001474 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001475 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001476 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001477 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001478 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001479 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001480 waitFor(cv);
1481 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001482 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1483 NET_CAPABILITY_VALIDATED));
1484 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001485 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001486 mCellNetworkAgent.disconnect();
1487 waitFor(cv);
1488 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001489 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001490 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001491 NET_CAPABILITY_VALIDATED));
1492 }
1493
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001494 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001495 public void testCellularOutscoresWeakWifi() throws Exception {
1496 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001497 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001498 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001499 mCellNetworkAgent.connect(true);
1500 waitFor(cv);
1501 verifyActiveNetwork(TRANSPORT_CELLULAR);
1502 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001503 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001504 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001505 mWiFiNetworkAgent.connect(true);
1506 waitFor(cv);
1507 verifyActiveNetwork(TRANSPORT_WIFI);
1508 // Test WiFi getting really weak.
Chalard Jean407deb72019-11-19 16:14:30 +09001509 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001510 mWiFiNetworkAgent.adjustScore(-11);
1511 waitFor(cv);
1512 verifyActiveNetwork(TRANSPORT_CELLULAR);
1513 // Test WiFi restoring signal strength.
Chalard Jean407deb72019-11-19 16:14:30 +09001514 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001515 mWiFiNetworkAgent.adjustScore(11);
1516 waitFor(cv);
1517 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001518 }
1519
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001520 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001521 public void testReapingNetwork() throws Exception {
1522 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1523 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001524 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001525 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001526 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001527 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1528 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001529 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001530 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001531 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001532 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001533 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001534 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001535 mWiFiNetworkAgent.connect(true);
1536 waitFor(cv);
1537 verifyActiveNetwork(TRANSPORT_WIFI);
1538 // Test bringing up unvalidated cellular.
1539 // Expect it to be torn down because it could never be the highest scoring network
1540 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001541 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001542 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001543 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001544 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001545 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001546 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001547 }
1548
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001549 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001550 public void testCellularFallback() throws Exception {
1551 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001552 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001553 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001554 mCellNetworkAgent.connect(true);
1555 waitFor(cv);
1556 verifyActiveNetwork(TRANSPORT_CELLULAR);
1557 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001558 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001559 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001560 mWiFiNetworkAgent.connect(true);
1561 waitFor(cv);
1562 verifyActiveNetwork(TRANSPORT_WIFI);
1563 // Reevaluate WiFi (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001564 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001565 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1566 NET_CAPABILITY_VALIDATED));
1567 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1568 // Should quickly fall back to Cellular.
1569 waitFor(cv);
1570 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1571 NET_CAPABILITY_VALIDATED));
1572 verifyActiveNetwork(TRANSPORT_CELLULAR);
1573 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001574 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001575 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1576 NET_CAPABILITY_VALIDATED));
1577 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1578 // Should quickly fall back to WiFi.
1579 waitFor(cv);
1580 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1581 NET_CAPABILITY_VALIDATED));
1582 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1583 NET_CAPABILITY_VALIDATED));
1584 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001585 }
1586
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001587 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001588 public void testWiFiFallback() throws Exception {
1589 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001590 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001591 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001592 mWiFiNetworkAgent.connect(false);
1593 waitFor(cv);
1594 verifyActiveNetwork(TRANSPORT_WIFI);
1595 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001596 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001597 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001598 mCellNetworkAgent.connect(true);
1599 waitFor(cv);
1600 verifyActiveNetwork(TRANSPORT_CELLULAR);
1601 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001602 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001603 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1604 NET_CAPABILITY_VALIDATED));
1605 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1606 // Should quickly fall back to WiFi.
1607 waitFor(cv);
1608 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1609 NET_CAPABILITY_VALIDATED));
1610 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001611 }
1612
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001613 @Test
1614 public void testRequiresValidation() {
1615 assertTrue(NetworkMonitorUtils.isValidationRequired(
1616 mCm.getDefaultRequest().networkCapabilities));
1617 }
1618
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001619 /**
1620 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1621 * this class receives, by calling expectCallback() exactly once each time a callback is
1622 * received. assertNoCallback may be called at any time.
1623 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001624 private class TestNetworkCallback extends TestableNetworkCallback {
Chalard Jeanb299b842019-09-27 17:13:14 +09001625 TestNetworkCallback() {
1626 super(TEST_CALLBACK_TIMEOUT_MS);
1627 }
1628
Chalard Jean6f4216f2019-06-05 01:40:32 +09001629 @Override
1630 public void assertNoCallback() {
1631 // TODO: better support this use case in TestableNetworkCallback
1632 waitForIdle();
1633 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001634 }
Paul Jensen3d911462015-06-12 06:40:24 -04001635
Erik Klineacdd6392016-07-07 16:50:58 +09001636 @Override
Chalard Jean059c4262019-09-30 17:51:12 +09001637 public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
Chalard Jean6f4216f2019-06-05 01:40:32 +09001638 final long timeoutMs) {
1639 final T callback = super.expectCallback(type, n, timeoutMs);
Chalard Jean059c4262019-09-30 17:51:12 +09001640 if (callback instanceof CallbackEntry.Losing) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09001641 // TODO : move this to the specific test(s) needing this rather than here.
Chalard Jean059c4262019-09-30 17:51:12 +09001642 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001643 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001644 String msg = String.format(
1645 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001646 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001647 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001648 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001649 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001650 }
1651 }
1652
1653 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1654 // only be declared in a static or top level type".
1655 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1656 for (TestNetworkCallback c : callbacks) {
1657 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001658 }
1659 }
1660
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001661 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001662 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001663 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001664 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1665 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001666 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1667 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001668 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1669 .addTransportType(TRANSPORT_WIFI).build();
1670 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1671 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001672 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001673 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1674 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1675
1676 // Test unvalidated networks
Chalard Jean407deb72019-11-19 16:14:30 +09001677 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001678 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001679 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001680 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1681 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001682 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1683 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001684 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001685
Paul Jensen3d911462015-06-12 06:40:24 -04001686 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1687 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001688 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001689 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001690 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1691
Chalard Jean407deb72019-11-19 16:14:30 +09001692 cv = registerConnectivityBroadcast(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001693 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001694 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001695 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1696 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001697 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1698 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001699 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001700
Chalard Jean407deb72019-11-19 16:14:30 +09001701 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001702 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001703 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1704 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001705 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001706 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001707 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001708
Chalard Jean407deb72019-11-19 16:14:30 +09001709 cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001710 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001711 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1712 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001713 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001714 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001715
1716 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001717 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001718 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001719 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1720 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001721 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001722 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001723
Paul Jensen3d911462015-06-12 06:40:24 -04001724 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1725 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001726 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001727 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001728 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1729
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001730 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001731 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001732 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001733 genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001734 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001735 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001736 cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001737 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001738 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001739
Paul Jensen3d911462015-06-12 06:40:24 -04001740 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001741 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1742 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001743 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001744
Paul Jensen3d911462015-06-12 06:40:24 -04001745 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001746 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1747 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001748 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001749 }
1750
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001751 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001752 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001753 // This test would be flaky with the default 120ms timer: that is short enough that
1754 // lingered networks are torn down before assertions can be run. We don't want to mock the
1755 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1756 // in detecting races.
1757 mService.mLingerDelayMs = 300;
1758
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001759 NetworkRequest request = new NetworkRequest.Builder()
1760 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1761 .build();
1762 TestNetworkCallback callback = new TestNetworkCallback();
1763 mCm.registerNetworkCallback(request, callback);
1764
1765 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1766 mCm.registerDefaultNetworkCallback(defaultCallback);
1767
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001768 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1769 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1770 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001771
1772 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1773 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1774 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1775
1776 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001777 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1778 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001779 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001780 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001781
1782 mWiFiNetworkAgent.connect(true);
1783 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1784 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001785 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001786 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001787 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001788 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001789 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001790 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001791 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001792
1793 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001794 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001795 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001796 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001797 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001798 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001799 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001800 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001801
1802 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001803 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
1804 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001805 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001806 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001807
1808 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001809 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001810 if (i % 2 == 0) {
1811 mWiFiNetworkAgent.adjustScore(-15);
1812 oldNetwork = mWiFiNetworkAgent;
1813 newNetwork = mCellNetworkAgent;
1814 } else {
1815 mWiFiNetworkAgent.adjustScore(15);
1816 oldNetwork = mCellNetworkAgent;
1817 newNetwork = mWiFiNetworkAgent;
1818
1819 }
Chalard Jean059c4262019-09-30 17:51:12 +09001820 callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001821 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1822 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001823 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001824 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1825 }
1826 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1827
1828 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1829 // if the network is still up.
1830 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001831 // We expect a notification about the capabilities change, and nothing else.
1832 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1833 defaultCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09001834 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001835 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001836
1837 // Wifi no longer satisfies our listen, which is for an unmetered network.
1838 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001839 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1840
1841 // Disconnect our test networks.
1842 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001843 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001844 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001845 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001846 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001847 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001848 waitForIdle();
1849 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001850
1851 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09001852 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001853
1854 // Check that a network is only lingered or torn down if it would not satisfy a request even
1855 // if it validated.
1856 request = new NetworkRequest.Builder().clearCapabilities().build();
1857 callback = new TestNetworkCallback();
1858
1859 mCm.registerNetworkCallback(request, callback);
1860
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001861 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001862 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09001863 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1864 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001865 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001866 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001867
1868 // Bring up wifi with a score of 20.
1869 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001870 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001871 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09001872 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1873 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001874 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001875 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001876
1877 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001878 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1879 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001880 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001881 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001882 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001883
1884 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001885 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001886 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001887 mWiFiNetworkAgent.adjustScore(50);
1888 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09001889 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001890 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001891 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001892 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001893 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001894
1895 // Tear down wifi.
1896 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001897 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1898 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001899 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001900 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001901 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001902
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001903 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1904 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001905 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001906 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001907 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001908 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001909 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001910 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001911 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001912 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001913 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001914
1915 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001916 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1917 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001918 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001919 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001920 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1921 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001922 waitForIdle();
1923 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001924
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001925 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001926 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001927 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001928 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1929 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001930 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001931 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001932 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001933 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1934 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001935 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001936 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001937 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001938 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001939
1940 NetworkRequest cellRequest = new NetworkRequest.Builder()
1941 .addTransportType(TRANSPORT_CELLULAR).build();
1942 NetworkCallback noopCallback = new NetworkCallback();
1943 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001944 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1945 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001946 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09001947 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001948
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001949 // Similar to the above: lingering can start even after the lingered request is removed.
1950 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001951 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001952 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1953 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001954 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001955 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001956
1957 // Cell is now the default network. Pin it with a cell-specific request.
1958 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1959 mCm.requestNetwork(cellRequest, noopCallback);
1960
1961 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001962 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001963 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001964 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1965 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001966 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001967 // The default request is lingering on cell, but nothing happens to cell, and we send no
1968 // callbacks for it, because it's kept up by cellRequest.
1969 callback.assertNoCallback();
1970 // Now unregister cellRequest and expect cell to start lingering.
1971 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09001972 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001973
1974 // Let linger run its course.
1975 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001976 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09001977 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001978
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001979 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
1980 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
1981 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001982 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001983 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001984 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001985 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001986 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001987 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001988 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
1989 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001990 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001991
1992 // Let linger run its course.
Chalard Jean059c4262019-09-30 17:51:12 +09001993 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001994
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001995 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001996 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001997 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
1998 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
1999 trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002000
2001 mCm.unregisterNetworkCallback(callback);
2002 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002003 mCm.unregisterNetworkCallback(trackDefaultCallback);
2004 }
2005
paulhu86e23eb2019-11-05 18:05:05 +08002006 private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
2007 final String testPackageName = mContext.getPackageName();
2008 when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
2009 .thenReturn(buildPackageInfo(true, uid));
2010 mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
2011 }
2012
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002013 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002014 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002015 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08002016 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Chalard Jean1fa777d2018-02-16 16:07:53 +09002017 NetworkRequest request = new NetworkRequest.Builder()
2018 .clearCapabilities()
2019 .build();
2020 TestNetworkCallback callback = new TestNetworkCallback();
2021 mCm.registerNetworkCallback(request, callback);
2022
2023 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2024 mCm.registerDefaultNetworkCallback(defaultCallback);
2025
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002026 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2027 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002028
2029 mCellNetworkAgent.connect(true);
2030 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2031 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2032
2033 // Wifi comes up and cell lingers.
2034 mWiFiNetworkAgent.connect(true);
2035 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2036 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002037 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002038 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2039
2040 // File a request for cellular, then release it.
2041 NetworkRequest cellRequest = new NetworkRequest.Builder()
2042 .addTransportType(TRANSPORT_CELLULAR).build();
2043 NetworkCallback noopCallback = new NetworkCallback();
2044 mCm.requestNetwork(cellRequest, noopCallback);
2045 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002046 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002047
2048 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002049 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002050 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2051 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2052 lingerTimeoutMs);
2053
2054 // Clean up.
2055 mCm.unregisterNetworkCallback(defaultCallback);
2056 mCm.unregisterNetworkCallback(callback);
2057 }
2058
2059 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002060 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002061 NetworkRequest request = new NetworkRequest.Builder()
2062 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2063 .build();
2064 TestNetworkCallback callback = new TestNetworkCallback();
2065 mCm.registerNetworkCallback(request, callback);
2066
2067 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002068 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002069 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002070 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002071
2072 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002073 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002074 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002075 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002076 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002077
2078 // Cell Remains the default.
2079 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2080
2081 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2082 // it's explicitly selected.
2083 mWiFiNetworkAgent.adjustScore(-40);
2084 mWiFiNetworkAgent.adjustScore(40);
2085 callback.assertNoCallback();
2086
2087 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2088 // wifi even though it's unvalidated.
2089 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002090 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002091 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2092
2093 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2094 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002095 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002096 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002097 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002098 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002099 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002100
2101 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2102 // network to disconnect.
2103 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002104 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002105
2106 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002107 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002108 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002109 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002110 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002111 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002112 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2113 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2114
2115 // BUG: the network will no longer linger, even though it's validated and outscored.
2116 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002117 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002118 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002119 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002120 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2121 callback.assertNoCallback();
2122
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002123 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
2124 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
2125 // wifi immediately.
2126 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002127 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002128 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002129 mWiFiNetworkAgent.explicitlySelected(true, true);
2130 mWiFiNetworkAgent.connect(false);
2131 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002132 callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002133 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2134 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002135 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002136
2137 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
2138 // Check that the network is not scored specially and that the device prefers cell data.
2139 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002140 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002141 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002142 mWiFiNetworkAgent.explicitlySelected(false, true);
2143 mWiFiNetworkAgent.connect(false);
2144 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2145 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2146
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002147 // Clean up.
2148 mWiFiNetworkAgent.disconnect();
2149 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002150
Chalard Jean059c4262019-09-30 17:51:12 +09002151 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2152 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002153 }
2154
Chalard Jean05ab6812018-05-02 21:14:54 +09002155 private int[] makeIntArray(final int size, final int value) {
2156 final int[] array = new int[size];
2157 Arrays.fill(array, value);
2158 return array;
2159 }
2160
Paul Jensen85cf78e2015-06-25 13:25:07 -04002161 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002162 // Verify NOT_RESTRICTED is set appropriately
2163 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2164 .build().networkCapabilities;
2165 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2166 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2167 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002168 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002169 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2170 } else {
2171 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2172 }
2173
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002174 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002175 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002176 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2177 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002178 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002179 mServiceContext, "testFactory", filter);
2180 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002181 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002182 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002183 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002184 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002185 int expectedRequestCount = 1;
2186 NetworkCallback networkCallback = null;
2187 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2188 // add one.
2189 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002190 assertFalse(testFactory.getMyStartRequested());
2191 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2192 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002193 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002194 mCm.requestNetwork(request, networkCallback);
2195 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002196 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002197 }
Paul Jensen3d911462015-06-12 06:40:24 -04002198 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002199 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2200 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002201
Paul Jensen85cf78e2015-06-25 13:25:07 -04002202 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002203 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002204 // Rather than create a validated network which complicates things by registering it's
2205 // own NetworkRequest during startup, just bump up the score to cancel out the
2206 // unvalidated penalty.
2207 testAgent.adjustScore(40);
2208 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002209
2210 // When testAgent connects, ConnectivityService will re-send us all current requests with
2211 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2212 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002213 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002214 testAgent.connect(false);
2215 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002216 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002217 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002218 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002219
Paul Jensen85cf78e2015-06-25 13:25:07 -04002220 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002221 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002222 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002223 ConnectivityManager.NetworkCallback[] networkCallbacks =
2224 new ConnectivityManager.NetworkCallback[10];
2225 for (int i = 0; i< networkCallbacks.length; i++) {
2226 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2227 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002228 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002229 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2230 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002231 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2232 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002233
Paul Jensen85cf78e2015-06-25 13:25:07 -04002234 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002235 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002236 for (int i = 0; i < networkCallbacks.length; i++) {
2237 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2238 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002239 testFactory.waitForNetworkRequests(expectedRequestCount);
2240 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002241
Paul Jensen85cf78e2015-06-25 13:25:07 -04002242 // Drop the higher scored network.
2243 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002244 // With the default network disconnecting, the requests are sent with score 0 to factories.
2245 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002246 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002247 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002248 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002249 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2250 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002251
2252 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002253 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002254 handlerThread.quit();
2255 }
2256
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002257 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002258 public void testNetworkFactoryRequests() throws Exception {
2259 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2260 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2261 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2262 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2263 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2264 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2265 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2266 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2267 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2268 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2269 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2270 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2271 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2272 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2273 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2274 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2275 }
2276
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002277 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002278 public void testNoMutableNetworkRequests() throws Exception {
2279 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002280 NetworkRequest request1 = new NetworkRequest.Builder()
2281 .addCapability(NET_CAPABILITY_VALIDATED)
2282 .build();
2283 NetworkRequest request2 = new NetworkRequest.Builder()
2284 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2285 .build();
2286
2287 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002288 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2289 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2290 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2291 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002292 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002293
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002294 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002295 public void testMMSonWiFi() throws Exception {
2296 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002297 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002298 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002299 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002300 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002301 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002302 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002303 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002304
Paul Jensene0988542015-06-25 15:30:08 -04002305 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002306 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09002307 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002308 mWiFiNetworkAgent.connect(true);
2309 waitFor(cv);
2310 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002311
Paul Jensene0988542015-06-25 15:30:08 -04002312 // Register MMS NetworkRequest
2313 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2314 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2315 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2316 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002317
Paul Jensene0988542015-06-25 15:30:08 -04002318 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002319 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002320 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002321 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002322 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002323 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002324
Paul Jensene0988542015-06-25 15:30:08 -04002325 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002326 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002327 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002328 verifyActiveNetwork(TRANSPORT_WIFI);
2329 }
2330
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002331 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002332 public void testMMSonCell() throws Exception {
2333 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002334 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09002335 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002336 mCellNetworkAgent.connect(false);
2337 waitFor(cv);
2338 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002339
Paul Jensene0988542015-06-25 15:30:08 -04002340 // Register MMS NetworkRequest
2341 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2342 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2343 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2344 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002345
Paul Jensene0988542015-06-25 15:30:08 -04002346 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002347 TestNetworkAgentWrapper
2348 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002349 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2350 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002351 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002352 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002353
Paul Jensene0988542015-06-25 15:30:08 -04002354 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002355 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002356 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002357 verifyActiveNetwork(TRANSPORT_CELLULAR);
2358 }
2359
lucaslinf3b59b32019-03-26 17:49:49 +08002360 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002361 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002362 // Register network callback.
2363 NetworkRequest request = new NetworkRequest.Builder()
2364 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2365 .build();
2366 TestNetworkCallback callback = new TestNetworkCallback();
2367 mCm.registerNetworkCallback(request, callback);
2368
2369 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002370 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002371 mCellNetworkAgent.connect(true);
2372 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2373
2374 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002375 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002376 mWiFiNetworkAgent.connectWithPartialConnectivity();
2377 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2378 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2379
2380 // Mobile data should be the default network.
2381 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2382 callback.assertNoCallback();
2383
lucaslinf3b59b32019-03-26 17:49:49 +08002384 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2385 // probe.
lucaslin783f2212019-10-22 18:27:33 +08002386 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
lucasline252a742019-03-12 13:08:03 +08002387 // If the user chooses yes to use this partial connectivity wifi, switch the default
2388 // network to wifi and check if wifi becomes valid or not.
2389 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2390 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002391 // If user accepts partial connectivity network,
2392 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002393 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002394 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002395
lucaslinf3b59b32019-03-26 17:49:49 +08002396 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2397 // validated.
2398 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002399 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002400 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2401 mWiFiNetworkAgent);
2402 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2403 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2404
2405 // Disconnect and reconnect wifi with partial connectivity again.
2406 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002407 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002408 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002409 mWiFiNetworkAgent.connectWithPartialConnectivity();
2410 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2411 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2412
2413 // Mobile data should be the default network.
2414 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2415
2416 // If the user chooses no, disconnect wifi immediately.
2417 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2418 false /* always */);
Chalard Jean059c4262019-09-30 17:51:12 +09002419 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002420
2421 // If user accepted partial connectivity before, and device reconnects to that network
2422 // again, but now the network has full connectivity. The network shouldn't contain
2423 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002424 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002425 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002426 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2427 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002428 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002429
lucaslinf3b59b32019-03-26 17:49:49 +08002430 // If user accepted partial connectivity network before,
2431 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2432 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002433 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002434 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002435 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002436 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2437 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002438
lucasline252a742019-03-12 13:08:03 +08002439 // Wifi should be the default network.
2440 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2441 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002442 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002443
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002444 // The user accepted partial connectivity and selected "don't ask again". Now the user
2445 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2446 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002447 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002448 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2449 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002450 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002451 // If user accepted partial connectivity network before,
2452 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2453 // ConnectivityService#updateNetworkInfo().
lucaslinf3b59b32019-03-26 17:49:49 +08002454 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002455 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002456 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002457 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002458 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
lucaslin783f2212019-10-22 18:27:33 +08002459 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002460
lucaslinf3b59b32019-03-26 17:49:49 +08002461 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2462 // validated.
2463 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2464 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2465 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002466 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002467
2468 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2469 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002470 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002471 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2472 true /* acceptUnvalidated */);
2473
2474 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2475 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2476 // notifyNetworkConnected.
lucaslin783f2212019-10-22 18:27:33 +08002477 mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002478 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002479 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002480 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002481 callback.expectCapabilitiesWith(
2482 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2483 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002484 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002485 }
2486
2487 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002488 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002489 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2490 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2491 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2492 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2493
2494 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2495 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2496 .addCapability(NET_CAPABILITY_VALIDATED).build();
2497 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2498
2499 // Bring up a network with a captive portal.
2500 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002501 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002502 String redirectUrl = "http://android.com/path";
lucaslin783f2212019-10-22 18:27:33 +08002503 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002504 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002505 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002506
2507 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2508 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2509 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2510 .launchCaptivePortalApp();
2511
2512 // Report that the captive portal is dismissed with partial connectivity, and check that
2513 // callbacks are fired.
2514 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002515 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002516 waitForIdle();
2517 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2518 mWiFiNetworkAgent);
2519
2520 // Report partial connectivity is accepted.
lucaslin783f2212019-10-22 18:27:33 +08002521 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002522 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2523 false /* always */);
2524 waitForIdle();
2525 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002526 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002527 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2528 NetworkCapabilities nc =
2529 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2530 mWiFiNetworkAgent);
2531
2532 mCm.unregisterNetworkCallback(captivePortalCallback);
2533 mCm.unregisterNetworkCallback(validatedCallback);
2534 }
2535
2536 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002537 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002538 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2539 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2540 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2541 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2542
2543 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2544 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2545 .addCapability(NET_CAPABILITY_VALIDATED).build();
2546 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002547
2548 // Bring up a network with a captive portal.
2549 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002550 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002551 String firstRedirectUrl = "http://example.com/firstPath";
lucaslin783f2212019-10-22 18:27:33 +08002552 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002553 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002554 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002555
2556 // Take down network.
2557 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002558 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002559 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002560
2561 // Bring up a network with a captive portal.
2562 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002563 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002564 String secondRedirectUrl = "http://example.com/secondPath";
lucaslin783f2212019-10-22 18:27:33 +08002565 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002566 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002567 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002568
2569 // Make captive portal disappear then revalidate.
2570 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
lucaslin783f2212019-10-22 18:27:33 +08002571 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002572 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002573 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002574
2575 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002576 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002577 // Expect no notification to be shown when captive portal disappears by itself
2578 verify(mNotificationManager, never()).notifyAsUser(
2579 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002580
2581 // Break network connectivity.
2582 // Expect NET_CAPABILITY_VALIDATED onLost callback.
lucaslin783f2212019-10-22 18:27:33 +08002583 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002584 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean059c4262019-09-30 17:51:12 +09002585 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002586 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002587
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002588 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002589 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002590 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2591 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2592 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2593 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2594
2595 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2596 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2597 .addCapability(NET_CAPABILITY_VALIDATED).build();
2598 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2599
2600 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002601 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002602 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002603 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002604 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2605
2606 // Check that calling startCaptivePortalApp does nothing.
2607 final int fastTimeoutMs = 100;
2608 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002609 waitForIdle();
2610 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002611 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2612
2613 // Turn into a captive portal.
lucaslin783f2212019-10-22 18:27:33 +08002614 mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002615 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002616 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002617 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002618
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002619 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002620 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002621 waitForIdle();
2622 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2623
2624 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2625 final Bundle testBundle = new Bundle();
2626 final String testKey = "testkey";
2627 final String testValue = "testvalue";
2628 testBundle.putString(testKey, testValue);
2629 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2630 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2631 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2632 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002633
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002634 // Report that the captive portal is dismissed, and check that callbacks are fired
lucaslin783f2212019-10-22 18:27:33 +08002635 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002636 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002637 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002638 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002639 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2640 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002641
2642 mCm.unregisterNetworkCallback(validatedCallback);
2643 mCm.unregisterNetworkCallback(captivePortalCallback);
2644 }
2645
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002646 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002647 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002648 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2649 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2650 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2651 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2652
2653 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2654 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2655 .addCapability(NET_CAPABILITY_VALIDATED).build();
2656 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2657
2658 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2659 // Bring up a network with a captive portal.
2660 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002661 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002662 String firstRedirectUrl = "http://example.com/firstPath";
2663
lucaslin783f2212019-10-22 18:27:33 +08002664 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002665 mWiFiNetworkAgent.expectDisconnected();
2666 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002667
2668 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002669 }
2670
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002671 private NetworkRequest.Builder newWifiRequestBuilder() {
2672 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2673 }
2674
Etan Cohen836ad572018-12-30 17:59:59 -08002675 /**
2676 * Verify request matching behavior with network specifiers.
2677 *
2678 * Note: this test is somewhat problematic since it involves removing capabilities from
2679 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2680 * as a WTF bug in
2681 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2682 * does work.
2683 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002684 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002685 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002686 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2687 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2688 Parcelable {
2689 @Override
2690 public boolean satisfiedBy(NetworkSpecifier other) {
2691 return true;
2692 }
2693
2694 @Override
2695 public int describeContents() {
2696 return 0;
2697 }
2698
2699 @Override
2700 public void writeToParcel(Parcel dest, int flags) {}
2701
2702 @Override
2703 public NetworkSpecifier redact() {
2704 return null;
2705 }
2706 }
2707
2708 // A network specifier that matches either another LocalNetworkSpecifier with the same
2709 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2710 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2711 private String mString;
2712
2713 LocalStringNetworkSpecifier(String string) {
2714 mString = string;
2715 }
2716
2717 @Override
2718 public boolean satisfiedBy(NetworkSpecifier other) {
2719 if (other instanceof LocalStringNetworkSpecifier) {
2720 return TextUtils.equals(mString,
2721 ((LocalStringNetworkSpecifier) other).mString);
2722 }
2723 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2724 return false;
2725 }
2726
2727 @Override
2728 public int describeContents() {
2729 return 0;
2730 }
2731 @Override
2732 public void writeToParcel(Parcel dest, int flags) {}
2733 }
2734
2735
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002736 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002737 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002738 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002739 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2740 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002741 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2742 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002743 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002744 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002745
2746 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2747 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2748 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002749 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002750 TestNetworkCallback cFoo = new TestNetworkCallback();
2751 TestNetworkCallback cBar = new TestNetworkCallback();
2752 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002753 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002754
2755 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2756 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2757 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002758 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002759 mCm.registerNetworkCallback(rFoo, cFoo);
2760 mCm.registerNetworkCallback(rBar, cBar);
2761
Etan Cohen836ad572018-12-30 17:59:59 -08002762 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2763 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2764
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002765 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002766 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002767 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2768 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2769 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2770 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002771 assertNoCallbacks(cFoo, cBar);
2772
Etan Cohen836ad572018-12-30 17:59:59 -08002773 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002774 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002775 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002776 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2777 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002778 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002779 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2780 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08002781 assertEquals(nsFoo,
2782 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002783 cFoo.assertNoCallback();
2784
Etan Cohen836ad572018-12-30 17:59:59 -08002785 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean059c4262019-09-30 17:51:12 +09002786 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002787 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002788 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002789 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2790 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002791 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002792 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2793 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08002794 assertEquals(nsBar,
2795 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2796 cBar.assertNoCallback();
2797
2798 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2799 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2800 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002801 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2802 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002803 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002804 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2805 (caps) -> caps.getNetworkSpecifier() == null);
2806 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2807 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002808 assertNull(
2809 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2810 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002811 cBar.assertNoCallback();
2812
2813 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean059c4262019-09-30 17:51:12 +09002814 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2815 cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002816 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean059c4262019-09-30 17:51:12 +09002817 c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002818 }
2819
Etan Cohen836ad572018-12-30 17:59:59 -08002820 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002821 }
2822
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002823 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002824 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09002825 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002826 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002827 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09002828 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002829
Chalard Jean751bb3f2019-06-19 23:29:58 +09002830 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002831 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2832 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002833 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002834 mService.requestNetwork(networkCapabilities, null, 0, null,
2835 ConnectivityManager.TYPE_WIFI);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002836 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002837
Etan Cohena7434272017-04-03 12:17:51 -07002838 class NonParcelableSpecifier extends NetworkSpecifier {
2839 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2840 };
2841 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2842 @Override public int describeContents() { return 0; }
2843 @Override public void writeToParcel(Parcel p, int flags) {}
2844 }
Etan Cohena7434272017-04-03 12:17:51 -07002845
Chalard Jean751bb3f2019-06-19 23:29:58 +09002846 final NetworkRequest.Builder builder =
2847 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2848 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002849 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2850 Parcel parcelW = Parcel.obtain();
2851 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002852 });
Etan Cohena7434272017-04-03 12:17:51 -07002853
Chalard Jean751bb3f2019-06-19 23:29:58 +09002854 final NetworkRequest nr =
2855 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
2856 .setNetworkSpecifier(new ParcelableSpecifier())
2857 .build();
Etan Cohena7434272017-04-03 12:17:51 -07002858 assertNotNull(nr);
2859
Chalard Jean751bb3f2019-06-19 23:29:58 +09002860 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002861 Parcel parcelW = Parcel.obtain();
2862 nr.writeToParcel(parcelW, 0);
2863 byte[] bytes = parcelW.marshall();
2864 parcelW.recycle();
2865
2866 Parcel parcelR = Parcel.obtain();
2867 parcelR.unmarshall(bytes, 0, bytes.length);
2868 parcelR.setDataPosition(0);
2869 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002870 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002871 }
2872
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002873 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002874 public void testNetworkSpecifierUidSpoofSecurityException() throws Exception {
Etan Cohen859748f2017-04-03 17:42:34 -07002875 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2876 @Override
2877 public boolean satisfiedBy(NetworkSpecifier other) {
2878 return true;
2879 }
2880
2881 @Override
2882 public void assertValidFromUid(int requestorUid) {
2883 throw new SecurityException("failure");
2884 }
2885
2886 @Override
2887 public int describeContents() { return 0; }
2888 @Override
2889 public void writeToParcel(Parcel dest, int flags) {}
2890 }
2891
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002892 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07002893 mWiFiNetworkAgent.connect(false);
2894
2895 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2896 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2897 networkSpecifier).build();
2898 TestNetworkCallback networkCallback = new TestNetworkCallback();
Chalard Jean751bb3f2019-06-19 23:29:58 +09002899 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07002900 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002901 });
Etan Cohen859748f2017-04-03 17:42:34 -07002902 }
2903
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002904 @Test
paulhu3d67f532019-03-22 16:35:06 +08002905 public void testInvalidSignalStrength() {
2906 NetworkRequest r = new NetworkRequest.Builder()
2907 .addCapability(NET_CAPABILITY_INTERNET)
2908 .addTransportType(TRANSPORT_WIFI)
2909 .setSignalStrength(-75)
2910 .build();
2911 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
2912 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09002913 assertThrows(SecurityException.class, () ->
2914 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08002915
Chalard Jean751bb3f2019-06-19 23:29:58 +09002916 assertThrows(SecurityException.class, () ->
2917 mCm.registerNetworkCallback(r, PendingIntent.getService(
2918 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08002919
2920 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09002921 assertThrows(IllegalArgumentException.class, () ->
2922 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08002923
Chalard Jean751bb3f2019-06-19 23:29:58 +09002924 assertThrows(IllegalArgumentException.class, () ->
2925 mCm.requestNetwork(r, PendingIntent.getService(
2926 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08002927 }
2928
2929 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002930 public void testRegisterDefaultNetworkCallback() throws Exception {
2931 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2932 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2933 defaultNetworkCallback.assertNoCallback();
2934
2935 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2936 // whenever Wi-Fi is up. Without this, the mobile network agent is
2937 // reaped before any other activity can take place.
2938 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2939 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2940 .addTransportType(TRANSPORT_CELLULAR).build();
2941 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2942 cellNetworkCallback.assertNoCallback();
2943
2944 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002945 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09002946 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002947 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2948 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002949 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002950
2951 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002952 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09002953 mWiFiNetworkAgent.connect(true);
2954 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002955 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002956 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002957
2958 // Bring down cell. Expect no default network callback, since it wasn't the default.
2959 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002960 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002961 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002962 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002963
2964 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002965 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09002966 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002967 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002968 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002969 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002970
2971 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2972 // followed by AVAILABLE cell.
2973 mWiFiNetworkAgent.disconnect();
2974 cellNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09002975 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002976 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002977 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002978 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2979 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002980 waitForIdle();
2981 assertEquals(null, mCm.getActiveNetwork());
2982
2983 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002984 final TestNetworkAgentWrapper
2985 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002986 final ArraySet<UidRange> ranges = new ArraySet<>();
2987 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002988 mMockVpn.setNetworkAgent(vpnNetworkAgent);
2989 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002990 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002991 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002992 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2993 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2994
2995 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002996 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002997 waitForIdle();
2998 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002999 }
3000
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003001 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003002 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003003 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003004 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003005 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3006 .addTransportType(TRANSPORT_CELLULAR).build();
3007 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3008
3009 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003010 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09003011 mCellNetworkAgent.connect(true);
3012
Erik Kline1d3db322017-02-28 16:20:20 +09003013 // We should get onAvailable(), onCapabilitiesChanged(), and
3014 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3015 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003016 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003017 cellNetworkCallback.assertNoCallback();
3018
3019 // Update LinkProperties.
3020 final LinkProperties lp = new LinkProperties();
3021 lp.setInterfaceName("foonet_data0");
3022 mCellNetworkAgent.sendLinkProperties(lp);
3023 // We should get onLinkPropertiesChanged().
Chalard Jean059c4262019-09-30 17:51:12 +09003024 cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Chalard Jean6f4216f2019-06-05 01:40:32 +09003025 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003026 cellNetworkCallback.assertNoCallback();
3027
Erik Kline1d3db322017-02-28 16:20:20 +09003028 // Suspend the network.
3029 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003030 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3031 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003032 cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003033 cellNetworkCallback.assertNoCallback();
3034
Erik Klineacdd6392016-07-07 16:50:58 +09003035 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003036 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003037 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003038 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3039 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003040 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003041 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003042 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3043
3044 mCellNetworkAgent.resume();
3045 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3046 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003047 cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09003048 cellNetworkCallback.assertNoCallback();
3049
3050 dfltNetworkCallback = new TestNetworkCallback();
3051 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3052 // This time onNetworkSuspended should not be called.
3053 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3054 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003055
Erik Klineacdd6392016-07-07 16:50:58 +09003056 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3057 mCm.unregisterNetworkCallback(cellNetworkCallback);
3058 }
3059
Calvin On1f64f3f2016-10-11 15:10:46 -07003060 private void setCaptivePortalMode(int mode) {
3061 ContentResolver cr = mServiceContext.getContentResolver();
3062 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3063 }
3064
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003065 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003066 ContentResolver cr = mServiceContext.getContentResolver();
3067 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003068 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003069 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003070 }
3071
Erik Kline79c6d052018-03-21 07:18:33 -07003072 private void setPrivateDnsSettings(String mode, String specifier) {
3073 final ContentResolver cr = mServiceContext.getContentResolver();
3074 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3075 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3076 mService.updatePrivateDnsSettings();
3077 waitForIdle();
3078 }
3079
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003080 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003081 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3082 assertNotNull(nc);
3083 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3084 }
3085
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003086 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003087 public void testBackgroundNetworks() throws Exception {
3088 // Create a background request. We can't do this ourselves because ConnectivityService
3089 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003090 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08003091 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003092 final NetworkRequest request = new NetworkRequest.Builder().build();
3093 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3094 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3095 final TestNetworkCallback callback = new TestNetworkCallback();
3096 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3097 mCm.registerNetworkCallback(request, callback);
3098 mCm.registerNetworkCallback(fgRequest, fgCallback);
3099
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003100 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003101 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003102 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3103 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003104 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3105
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003106 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003107 mWiFiNetworkAgent.connect(true);
3108
3109 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003110 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003111 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003112 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003113 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003114 fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003115 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003116 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3117 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3118
3119 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003120 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003121 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09003122 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003123 // Expect a network capabilities update sans FOREGROUND.
3124 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003125 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3126 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3127
3128 // File a cell request and check that cell comes into the foreground.
3129 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3130 .addTransportType(TRANSPORT_CELLULAR).build();
3131 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3132 mCm.requestNetwork(cellRequest, cellCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003133 // NOTE: This request causes the network's capabilities to change. This
3134 // is currently delivered before the onAvailable() callbacks.
3135 // TODO: Fix this.
3136 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003137 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3138 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003139 // Expect a network capabilities update with FOREGROUND, because the most recent
3140 // request causes its state to change.
3141 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003142 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3143 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3144
3145 // Release the request. The network immediately goes into the background, since it was not
3146 // lingering.
3147 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09003148 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003149 // Expect a network capabilities update sans FOREGROUND.
3150 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003151 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3152 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3153
3154 // Disconnect wifi and check that cell is foreground again.
3155 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003156 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3157 fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003158 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003159 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3160
3161 mCm.unregisterNetworkCallback(callback);
3162 mCm.unregisterNetworkCallback(fgCallback);
3163 }
3164
Hugo Benichi849b81b2017-05-25 13:42:31 +09003165 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003166 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003167 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003168 // Benchmarks connecting and switching performance in the presence of a large number of
3169 // NetworkRequests.
3170 // 1. File NUM_REQUESTS requests.
3171 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3172 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3173 // and NUM_REQUESTS onAvailable callbacks to fire.
3174 // See how long it took.
3175 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003176 final int REGISTER_TIME_LIMIT_MS = 200;
3177 final int CONNECT_TIME_LIMIT_MS = 60;
3178 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003179 final int UNREGISTER_TIME_LIMIT_MS = 20;
3180
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003181 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3182 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3183 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3184 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3185
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003186 for (int i = 0; i < NUM_REQUESTS; i++) {
3187 callbacks[i] = new NetworkCallback() {
3188 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3189 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3190 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003191 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003192
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003193 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003194 for (NetworkCallback cb : callbacks) {
3195 mCm.registerNetworkCallback(request, cb);
3196 }
3197 });
3198
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003199 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003200 // Don't request that the network validate, because otherwise connect() will block until
3201 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3202 // and we won't actually measure anything.
3203 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003204
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003205 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003206 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003207 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003208 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3209 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3210 onAvailableDispatchingDuration));
3211 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3212 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3213 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003214
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003215 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003216 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003217 mWiFiNetworkAgent.adjustScore(40);
3218 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003219
3220 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003221 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003222 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003223 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3224 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3225 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3226 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3227 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003228
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003229 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003230 for (NetworkCallback cb : callbacks) {
3231 mCm.unregisterNetworkCallback(cb);
3232 }
3233 });
3234 }
3235
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003236 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003237 public void testMobileDataAlwaysOn() throws Exception {
paulhu86e23eb2019-11-05 18:05:05 +08003238 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003239 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3240 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3241 .addTransportType(TRANSPORT_CELLULAR).build();
3242 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3243
3244 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3245 handlerThread.start();
3246 NetworkCapabilities filter = new NetworkCapabilities()
3247 .addTransportType(TRANSPORT_CELLULAR)
3248 .addCapability(NET_CAPABILITY_INTERNET);
3249 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3250 mServiceContext, "testFactory", filter);
3251 testFactory.setScoreFilter(40);
3252
3253 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003254 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003255 testFactory.register();
3256 testFactory.waitForNetworkRequests(1);
3257 assertTrue(testFactory.getMyStartRequested());
3258
3259 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003260 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003261 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3262 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003263 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003264 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003265 assertFalse(testFactory.getMyStartRequested());
3266
3267 ContentResolver cr = mServiceContext.getContentResolver();
3268
3269 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003270 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003271 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003272 testFactory.waitForNetworkRequests(2);
3273 assertTrue(testFactory.getMyStartRequested());
3274
3275 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003276 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003277 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003278 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003279 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003280 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003281 testFactory.waitForNetworkRequests(2);
3282 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3283
3284 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003285 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003286 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003287 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003288
3289 // Turn off mobile data always on and expect the request to disappear...
3290 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003291 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003292 testFactory.waitForNetworkRequests(1);
3293
3294 // ... and cell data to be torn down.
Chalard Jean059c4262019-09-30 17:51:12 +09003295 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003296 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003297
3298 testFactory.unregister();
3299 mCm.unregisterNetworkCallback(cellNetworkCallback);
3300 handlerThread.quit();
3301 }
3302
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003303 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003304 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003305 final ContentResolver cr = mServiceContext.getContentResolver();
3306 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3307
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003308 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003309 String[] values = new String[] {null, "0", "1"};
3310 for (int i = 0; i < values.length; i++) {
3311 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003312 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003313 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003314 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003315 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003316 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003317 }
3318
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003319 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003320
3321 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003322 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003323 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003324 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003325 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003326
3327 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003328 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003329 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003330 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003331 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003332
3333 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003334 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003335 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003336 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003337 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003338 }
3339
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003340 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003341 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003342 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003343
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003344 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003345 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003346
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003347 // File a request for cell to ensure it doesn't go down.
3348 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3349 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3350 .addTransportType(TRANSPORT_CELLULAR).build();
3351 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3352
3353 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3354 mCm.registerDefaultNetworkCallback(defaultCallback);
3355
3356 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3357 .addTransportType(TRANSPORT_WIFI)
3358 .addCapability(NET_CAPABILITY_VALIDATED)
3359 .build();
3360 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3361 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3362
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003363 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003364 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003365
3366 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003367 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003368 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003369 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3370 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003371 Network cellNetwork = mCellNetworkAgent.getNetwork();
3372
3373 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003374 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003375 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003376 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3377 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003378 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3379
3380 // Fail validation on wifi.
lucaslin783f2212019-10-22 18:27:33 +08003381 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003382 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003383 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003384 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003385
3386 // Because avoid bad wifi is off, we don't switch to cellular.
3387 defaultCallback.assertNoCallback();
3388 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3389 NET_CAPABILITY_VALIDATED));
3390 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3391 NET_CAPABILITY_VALIDATED));
3392 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3393
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003394 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3395 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003396 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3397 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003398 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003399 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3400
3401 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003402 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3403 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003404 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003405 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3406
3407 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3408 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003409 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003410 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3411 NET_CAPABILITY_VALIDATED));
3412 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3413 NET_CAPABILITY_VALIDATED));
3414 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3415
3416 // Disconnect and reconnect wifi to clear the one-time switch above.
3417 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003418 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003419 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003420 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3421 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003422 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3423
3424 // Fail validation on wifi and expect the dialog to appear.
lucaslin783f2212019-10-22 18:27:33 +08003425 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003426 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003427 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003428 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003429
3430 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003431 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003432 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003433
3434 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003435 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003436 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3437 NET_CAPABILITY_VALIDATED));
3438 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3439 NET_CAPABILITY_VALIDATED));
3440 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3441
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003442 // Simulate the user turning the cellular fallback setting off and then on.
3443 // We switch to wifi and then to cell.
3444 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003445 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003446 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003447 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3448 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003449 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003450 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003451 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3452
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003453 // If cell goes down, we switch to wifi.
3454 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003455 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003456 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003457 validatedWifiCallback.assertNoCallback();
3458
3459 mCm.unregisterNetworkCallback(cellNetworkCallback);
3460 mCm.unregisterNetworkCallback(validatedWifiCallback);
3461 mCm.unregisterNetworkCallback(defaultCallback);
3462 }
3463
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003464 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003465 public void testMeteredMultipathPreferenceSetting() throws Exception {
3466 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003467 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3468
3469 for (int config : Arrays.asList(0, 3, 2)) {
3470 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003471 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003472 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003473 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003474 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003475
3476 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3477 String msg = String.format("config=%d, setting=%s", config, setting);
3478 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3479 }
3480 }
3481 }
3482
Erik Kline3841a482015-11-25 12:49:38 +09003483 /**
3484 * Validate that a satisfied network request does not trigger onUnavailable() once the
3485 * time-out period expires.
3486 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003487 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003488 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003489 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3490 NetworkCapabilities.TRANSPORT_WIFI).build();
3491 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003492 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003493
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003494 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003495 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003496 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003497 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003498
3499 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003500 networkCallback.assertNoCallback();
3501 }
3502
3503 /**
3504 * Validate that a satisfied network request followed by a disconnected (lost) network does
3505 * not trigger onUnavailable() once the time-out period expires.
3506 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003507 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003508 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003509 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3510 NetworkCapabilities.TRANSPORT_WIFI).build();
3511 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003512 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003513
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003514 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003515 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003516 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003517 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003518 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003519 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003520
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003521 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003522 networkCallback.assertNoCallback();
3523 }
3524
3525 /**
3526 * Validate that when a time-out is specified for a network request the onUnavailable()
3527 * callback is called when time-out expires. Then validate that if network request is
3528 * (somehow) satisfied - the callback isn't called later.
3529 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003530 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003531 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003532 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3533 NetworkCapabilities.TRANSPORT_WIFI).build();
3534 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003535 final int timeoutMs = 10;
3536 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003537
3538 // pass timeout and validate that UNAVAILABLE is called
Chalard Jean059c4262019-09-30 17:51:12 +09003539 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Erik Kline3841a482015-11-25 12:49:38 +09003540
3541 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003542 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003543 mWiFiNetworkAgent.connect(false);
3544 networkCallback.assertNoCallback();
3545 }
3546
3547 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003548 * Validate that when a network request is unregistered (cancelled), no posterior event can
3549 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003550 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003551 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003552 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003553 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3554 NetworkCapabilities.TRANSPORT_WIFI).build();
3555 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003556 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003557
Hugo Benichidfb559a2016-12-20 14:57:49 +09003558 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003559 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003560 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3561 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003562 networkCallback.assertNoCallback();
3563
3564 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003565 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003566 mWiFiNetworkAgent.connect(false);
3567 networkCallback.assertNoCallback();
3568 }
3569
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003570 @Test
3571 public void testUnfulfillableNetworkRequest() throws Exception {
3572 runUnfulfillableNetworkRequest(false);
3573 }
3574
3575 @Test
3576 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3577 runUnfulfillableNetworkRequest(true);
3578 }
3579
Etan Cohenddb720a2019-01-08 12:09:18 -08003580 /**
3581 * Validate the callback flow for a factory releasing a request as unfulfillable.
3582 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003583 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003584 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3585 NetworkCapabilities.TRANSPORT_WIFI).build();
3586 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3587
3588 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3589 handlerThread.start();
3590 NetworkCapabilities filter = new NetworkCapabilities()
3591 .addTransportType(TRANSPORT_WIFI)
3592 .addCapability(NET_CAPABILITY_INTERNET);
3593 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3594 mServiceContext, "testFactory", filter);
3595 testFactory.setScoreFilter(40);
3596
3597 // Register the factory and expect it to receive the default request.
Etan Cohenae574a82019-01-08 12:09:18 -08003598 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003599 testFactory.register();
3600 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3601
3602 assertEquals(1, requests.size()); // have 1 request at this point
3603 int origRequestId = requests.valueAt(0).requestId;
3604
3605 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003606 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003607 mCm.requestNetwork(nr, networkCallback);
3608 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3609
3610 int newRequestId = 0;
3611 for (int i = 0; i < requests.size(); ++i) {
3612 if (requests.valueAt(i).requestId != origRequestId) {
3613 newRequestId = requests.valueAt(i).requestId;
3614 break;
3615 }
3616 }
3617
Etan Cohen22e0fc12019-05-23 08:16:20 -07003618 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003619 if (preUnregister) {
3620 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003621
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003622 // Simulate the factory releasing the request as unfulfillable: no-op since
3623 // the callback has already been unregistered (but a test that no exceptions are
3624 // thrown).
3625 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3626 } else {
3627 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003628 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3629
Chalard Jean059c4262019-09-30 17:51:12 +09003630 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003631 testFactory.waitForRequests();
3632
3633 // unregister network callback - a no-op (since already freed by the
3634 // on-unavailable), but should not fail or throw exceptions.
3635 mCm.unregisterNetworkCallback(networkCallback);
3636 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003637
Etan Cohenddb720a2019-01-08 12:09:18 -08003638 testFactory.unregister();
3639 handlerThread.quit();
3640 }
3641
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003642 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3643
Chalard Jeane7b24752019-06-20 16:01:19 +09003644 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003645
3646 private class CallbackValue {
3647 public CallbackType callbackType;
3648 public int error;
3649
3650 public CallbackValue(CallbackType type) {
3651 this.callbackType = type;
3652 this.error = PacketKeepalive.SUCCESS;
3653 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3654 }
3655
3656 public CallbackValue(CallbackType type, int error) {
3657 this.callbackType = type;
3658 this.error = error;
3659 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3660 }
3661
3662 @Override
3663 public boolean equals(Object o) {
3664 return o instanceof CallbackValue &&
3665 this.callbackType == ((CallbackValue) o).callbackType &&
3666 this.error == ((CallbackValue) o).error;
3667 }
3668
3669 @Override
3670 public String toString() {
3671 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3672 }
3673 }
3674
junyulai7c469172019-01-16 20:23:34 +08003675 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003676
3677 @Override
3678 public void onStarted() {
3679 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3680 }
3681
3682 @Override
3683 public void onStopped() {
3684 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3685 }
3686
3687 @Override
3688 public void onError(int error) {
3689 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3690 }
3691
Chalard Jeane7b24752019-06-20 16:01:19 +09003692 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3693 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003694 }
3695
Chalard Jeane7b24752019-06-20 16:01:19 +09003696 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003697 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3698 }
3699
Chalard Jeane7b24752019-06-20 16:01:19 +09003700 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003701 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3702 }
3703
Chalard Jeane7b24752019-06-20 16:01:19 +09003704 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003705 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3706 }
3707 }
3708
junyulai48eac1d42018-12-27 17:25:29 +08003709 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3710
3711 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3712
3713 private class CallbackValue {
3714 public CallbackType callbackType;
3715 public int error;
3716
3717 CallbackValue(CallbackType type) {
3718 this.callbackType = type;
3719 this.error = SocketKeepalive.SUCCESS;
3720 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3721 }
3722
3723 CallbackValue(CallbackType type, int error) {
3724 this.callbackType = type;
3725 this.error = error;
3726 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3727 }
3728
3729 @Override
3730 public boolean equals(Object o) {
3731 return o instanceof CallbackValue
3732 && this.callbackType == ((CallbackValue) o).callbackType
3733 && this.error == ((CallbackValue) o).error;
3734 }
3735
3736 @Override
3737 public String toString() {
3738 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3739 error);
3740 }
3741 }
3742
3743 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003744 private final Executor mExecutor;
3745
3746 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3747 mExecutor = executor;
3748 }
junyulai48eac1d42018-12-27 17:25:29 +08003749
3750 @Override
3751 public void onStarted() {
3752 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3753 }
3754
3755 @Override
3756 public void onStopped() {
3757 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3758 }
3759
3760 @Override
3761 public void onError(int error) {
3762 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3763 }
3764
Chalard Jeane7b24752019-06-20 16:01:19 +09003765 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3766 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3767
junyulai48eac1d42018-12-27 17:25:29 +08003768 }
3769
Chalard Jeane7b24752019-06-20 16:01:19 +09003770 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003771 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3772 }
3773
Chalard Jeane7b24752019-06-20 16:01:19 +09003774 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003775 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3776 }
3777
Chalard Jeane7b24752019-06-20 16:01:19 +09003778 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003779 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3780 }
junyulai7c469172019-01-16 20:23:34 +08003781
3782 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003783 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08003784 CallbackValue cv = mCallbacks.peek();
3785 assertNull("Unexpected callback: " + cv, cv);
3786 }
junyulai48eac1d42018-12-27 17:25:29 +08003787 }
3788
Chalard Jeane7b24752019-06-20 16:01:19 +09003789 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003790 // Ensure the network is disconnected before we do anything.
3791 if (mWiFiNetworkAgent != null) {
3792 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3793 }
3794
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003795 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09003796 ConditionVariable cv = registerConnectivityBroadcast(1);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003797 mWiFiNetworkAgent.connect(true);
3798 waitFor(cv);
3799 verifyActiveNetwork(TRANSPORT_WIFI);
3800 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003801 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003802 return mWiFiNetworkAgent.getNetwork();
3803 }
3804
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003805 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07003806 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003807 public void testPacketKeepalives() throws Exception {
3808 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3809 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3810 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3811 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3812 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3813
Nathan Harold63dd8132018-02-14 13:09:45 -08003814 final int validKaInterval = 15;
3815 final int invalidKaInterval = 9;
3816
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003817 LinkProperties lp = new LinkProperties();
3818 lp.setInterfaceName("wlan12");
3819 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3820 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3821 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3822 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3823
3824 Network notMyNet = new Network(61234);
3825 Network myNet = connectKeepaliveNetwork(lp);
3826
3827 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3828 PacketKeepalive ka;
3829
3830 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003831 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003832 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3833
Nathan Harold63dd8132018-02-14 13:09:45 -08003834 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003835 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3836
Nathan Harold63dd8132018-02-14 13:09:45 -08003837 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003838 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3839
Nathan Harold63dd8132018-02-14 13:09:45 -08003840 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003841 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3842
Nathan Harold63dd8132018-02-14 13:09:45 -08003843 // NAT-T is only supported for IPv4.
3844 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3845 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003846
Nathan Harold63dd8132018-02-14 13:09:45 -08003847 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003848 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3849
Nathan Harold63dd8132018-02-14 13:09:45 -08003850 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003851 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3852
Nathan Harold63dd8132018-02-14 13:09:45 -08003853 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003854 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3855
Nathan Harold63dd8132018-02-14 13:09:45 -08003856 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003857 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3858
3859 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003860 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003861 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003862 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003863 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003864 ka.stop();
3865 callback.expectStopped();
3866
3867 // Check that deleting the IP address stops the keepalive.
3868 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003869 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003870 callback.expectStarted();
3871 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3872 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3873 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3874 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3875 mWiFiNetworkAgent.sendLinkProperties(lp);
3876
3877 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003878 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003879 callback.expectStarted();
3880 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003881 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003882 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3883
3884 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003885 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003886 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003887 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003888 ka.stop();
3889
3890 // Reconnect.
3891 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003892 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003893
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003894 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3895 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003896 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003897 callback.expectStarted();
3898
3899 // The second one gets slot 2.
3900 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3901 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003902 PacketKeepalive ka2 = mCm.startNattKeepalive(
3903 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003904 callback2.expectStarted();
3905
3906 // Now stop the first one and create a third. This also gets slot 1.
3907 ka.stop();
3908 callback.expectStopped();
3909
3910 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3911 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003912 PacketKeepalive ka3 = mCm.startNattKeepalive(
3913 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003914 callback3.expectStarted();
3915
3916 ka2.stop();
3917 callback2.expectStopped();
3918
3919 ka3.stop();
3920 callback3.expectStopped();
3921 }
Udam Sainib7c24872016-01-04 12:16:14 -08003922
Xiao Maa4637112019-02-07 15:03:57 +09003923 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09003924 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
3925 throws Exception {
junyulai06835112019-01-03 18:50:15 +08003926 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09003927 final Executor executorInline = (Runnable r) -> r.run();
3928 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08003929 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09003930 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003931 }
junyulai06835112019-01-03 18:50:15 +08003932
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003933 @Test
junyulaiafe9b492019-03-19 18:50:23 +08003934 public void testNattSocketKeepalives() throws Exception {
3935 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
3936 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08003937 }
3938
3939 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08003940 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08003941 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08003942 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08003943 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3944 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3945 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3946 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3947 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3948
3949 final int validKaInterval = 15;
3950 final int invalidKaInterval = 9;
3951
3952 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08003953 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
3954 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08003955
junyulai48eac1d42018-12-27 17:25:29 +08003956 LinkProperties lp = new LinkProperties();
3957 lp.setInterfaceName("wlan12");
3958 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3959 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3960 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3961 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3962
3963 Network notMyNet = new Network(61234);
3964 Network myNet = connectKeepaliveNetwork(lp);
3965
junyulai7c469172019-01-16 20:23:34 +08003966 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08003967
3968 // Attempt to start keepalives with invalid parameters and check for errors.
3969 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08003970 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3971 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3972 ka.start(validKaInterval);
3973 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3974 }
junyulai48eac1d42018-12-27 17:25:29 +08003975
3976 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08003977 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3978 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3979 ka.start(invalidKaInterval);
3980 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
3981 }
junyulai48eac1d42018-12-27 17:25:29 +08003982
3983 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08003984 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3985 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
3986 ka.start(validKaInterval);
3987 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3988 }
junyulai48eac1d42018-12-27 17:25:29 +08003989
3990 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08003991 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3992 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
3993 ka.start(validKaInterval);
3994 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3995 }
junyulai48eac1d42018-12-27 17:25:29 +08003996
3997 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08003998 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3999 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4000 ka.start(validKaInterval);
4001 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4002 }
junyulai48eac1d42018-12-27 17:25:29 +08004003
4004 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004005 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4006 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4007 ka.start(validKaInterval);
4008 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4009 }
junyulai48eac1d42018-12-27 17:25:29 +08004010
4011 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004012 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004013 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4014 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4015 ka.start(validKaInterval);
4016 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004017 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004018 ka.stop();
4019 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004020
junyulai0c666972019-03-04 22:45:36 +08004021 // Check that keepalive could be restarted.
4022 ka.start(validKaInterval);
4023 callback.expectStarted();
4024 ka.stop();
4025 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004026
junyulai0c666972019-03-04 22:45:36 +08004027 // Check that keepalive can be restarted without waiting for callback.
4028 ka.start(validKaInterval);
4029 callback.expectStarted();
4030 ka.stop();
4031 ka.start(validKaInterval);
4032 callback.expectStopped();
4033 callback.expectStarted();
4034 ka.stop();
4035 callback.expectStopped();
4036 }
junyulai7c469172019-01-16 20:23:34 +08004037
junyulai48eac1d42018-12-27 17:25:29 +08004038 // Check that deleting the IP address stops the keepalive.
4039 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004040 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4041 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4042 ka.start(validKaInterval);
4043 callback.expectStarted();
4044 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4045 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4046 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4047 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4048 mWiFiNetworkAgent.sendLinkProperties(lp);
4049 }
junyulai48eac1d42018-12-27 17:25:29 +08004050
4051 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004052 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4053 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4054 ka.start(validKaInterval);
4055 callback.expectStarted();
4056 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004057 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004058 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004059
junyulai0c666972019-03-04 22:45:36 +08004060 // ... and that stopping it after that has no adverse effects.
4061 waitForIdle();
4062 final Network myNetAlias = myNet;
4063 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4064 ka.stop();
4065 callback.assertNoCallback();
4066 }
junyulai48eac1d42018-12-27 17:25:29 +08004067
4068 // Reconnect.
4069 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004070 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08004071
4072 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4073 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004074 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004075 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4076 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4077 ka.start(validKaInterval);
4078 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004079
junyulai0c666972019-03-04 22:45:36 +08004080 // The second one gets slot 2.
4081 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004082 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4083 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004084 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4085 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4086 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4087 ka2.start(validKaInterval);
4088 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004089
junyulai0c666972019-03-04 22:45:36 +08004090 ka.stop();
4091 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004092
junyulai0c666972019-03-04 22:45:36 +08004093 ka2.stop();
4094 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004095
junyulai0c666972019-03-04 22:45:36 +08004096 testSocket.close();
4097 testSocket2.close();
4098 }
4099 }
junyulai06835112019-01-03 18:50:15 +08004100
junyulai15178152019-03-27 11:00:37 +08004101 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004102 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4103 // assertFalse(isUdpPortInUse(srcPort));
4104 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004105
junyulai06835112019-01-03 18:50:15 +08004106 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004107 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004108 mWiFiNetworkAgent = null;
4109 }
4110
4111 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004112 public void testTcpSocketKeepalives() throws Exception {
4113 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004114 }
4115
4116 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4117 final int srcPortV4 = 12345;
4118 final int srcPortV6 = 23456;
4119 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4120 final InetAddress myIPv6 = InetAddress.getByName("::1");
4121
4122 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004123
4124 final LinkProperties lp = new LinkProperties();
4125 lp.setInterfaceName("wlan12");
4126 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4127 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4128 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4129 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4130
4131 final Network notMyNet = new Network(61234);
4132 final Network myNet = connectKeepaliveNetwork(lp);
4133
4134 final Socket testSocketV4 = new Socket();
4135 final Socket testSocketV6 = new Socket();
4136
junyulai7c469172019-01-16 20:23:34 +08004137 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004138
4139 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4140 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004141 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4142 notMyNet, testSocketV4, executor, callback)) {
4143 ka.start(validKaInterval);
4144 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4145 }
Xiao Maa4637112019-02-07 15:03:57 +09004146
4147 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004148 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4149 myNet, testSocketV4, executor, callback)) {
4150 ka.start(validKaInterval);
4151 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4152 }
Xiao Maa4637112019-02-07 15:03:57 +09004153
4154 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004155 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4156 myNet, testSocketV6, executor, callback)) {
4157 ka.start(validKaInterval);
4158 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4159 }
Xiao Maa4637112019-02-07 15:03:57 +09004160
4161 // Bind the socket address
4162 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4163 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4164
4165 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004166 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4167 myNet, testSocketV4, executor, callback)) {
4168 ka.start(validKaInterval);
4169 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4170 }
Xiao Maa4637112019-02-07 15:03:57 +09004171
4172 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004173 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4174 myNet, testSocketV6, executor, callback)) {
4175 ka.start(validKaInterval);
4176 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4177 }
Xiao Maa4637112019-02-07 15:03:57 +09004178
4179 testSocketV4.close();
4180 testSocketV6.close();
4181
4182 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004183 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004184 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004185 }
4186
junyulai0c666972019-03-04 22:45:36 +08004187 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004188 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4189 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4190 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4191 final int validKaInterval = 15;
4192
4193 // Prepare the target network.
4194 LinkProperties lp = new LinkProperties();
4195 lp.setInterfaceName("wlan12");
4196 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4197 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4198 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004199 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4200 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004201
4202 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4203
4204 // Prepare the target file descriptor, keep only one instance.
4205 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004206 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4207 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004208 final ParcelFileDescriptor testPfd =
4209 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4210 testSocket.close();
4211 assertTrue(isUdpPortInUse(srcPort));
4212
4213 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4214 // block.
4215 try (SocketKeepalive ka = mCm.createNattKeepalive(
4216 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4217 ka.start(validKaInterval);
4218 callback.expectStarted();
4219 ka.stop();
4220 callback.expectStopped();
4221 }
4222
4223 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4224 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4225 // address.
4226 assertTrue(isUdpPortInUse(srcPort));
4227 final InetSocketAddress sa =
4228 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4229 assertEquals(anyIPv4, sa.getAddress());
4230
4231 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004232 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4233 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004234
4235 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004236 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004237 mWiFiNetworkAgent = null;
4238 }
4239
4240 private static boolean isUdpPortInUse(int port) {
4241 try (DatagramSocket ignored = new DatagramSocket(port)) {
4242 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004243 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004244 return true;
4245 }
4246 }
4247
junyulai48eac1d42018-12-27 17:25:29 +08004248 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004249 public void testGetCaptivePortalServerUrl() throws Exception {
4250 String url = mCm.getCaptivePortalServerUrl();
4251 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4252 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004253
4254 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004255 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004256 synchronized(sLock) {
4257 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004258 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004259 }
4260 return sNetwork != null;
4261 }
4262 }
4263
Chalard Jeane7b24752019-06-20 16:01:19 +09004264 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004265 synchronized(sLock) {
4266 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004267 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004268 }
4269 return sNetwork == null;
4270 }
4271 }
4272 }
4273
4274 private void assertPinnedToWifiWithCellDefault() {
4275 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4276 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4277 }
4278
4279 private void assertPinnedToWifiWithWifiDefault() {
4280 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4281 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4282 }
4283
4284 private void assertNotPinnedToWifi() {
4285 assertNull(mCm.getBoundNetworkForProcess());
4286 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4287 }
4288
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004289 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004290 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004291 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4292 .addTransportType(TRANSPORT_WIFI)
4293 .build();
4294 assertNull(mCm.getBoundNetworkForProcess());
4295
4296 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4297 assertNull(mCm.getBoundNetworkForProcess());
4298
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004299 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004300 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004301 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004302 mWiFiNetworkAgent.connect(false);
4303
4304 // When wi-fi connects, expect to be pinned.
4305 assertTrue(TestNetworkPinner.awaitPin(100));
4306 assertPinnedToWifiWithCellDefault();
4307
4308 // Disconnect and expect the pin to drop.
4309 mWiFiNetworkAgent.disconnect();
4310 assertTrue(TestNetworkPinner.awaitUnpin(100));
4311 assertNotPinnedToWifi();
4312
4313 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004314 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004315 mWiFiNetworkAgent.connect(false);
4316 assertFalse(TestNetworkPinner.awaitPin(100));
4317 assertNotPinnedToWifi();
4318
4319 // Pinning while connected causes the pin to take effect immediately.
4320 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4321 assertTrue(TestNetworkPinner.awaitPin(100));
4322 assertPinnedToWifiWithCellDefault();
4323
4324 // Explicitly unpin and expect to use the default network again.
4325 TestNetworkPinner.unpin();
4326 assertNotPinnedToWifi();
4327
4328 // Disconnect cell and wifi.
Chalard Jean407deb72019-11-19 16:14:30 +09004329 ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004330 mCellNetworkAgent.disconnect();
4331 mWiFiNetworkAgent.disconnect();
4332 waitFor(cv);
4333
4334 // Pinning takes effect even if the pinned network is the default when the pin is set...
4335 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004336 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004337 mWiFiNetworkAgent.connect(false);
4338 assertTrue(TestNetworkPinner.awaitPin(100));
4339 assertPinnedToWifiWithWifiDefault();
4340
4341 // ... and is maintained even when that network is no longer the default.
Chalard Jean407deb72019-11-19 16:14:30 +09004342 cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004343 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004344 mCellNetworkAgent.connect(true);
4345 waitFor(cv);
4346 assertPinnedToWifiWithCellDefault();
4347 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004348
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004349 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004350 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004351 // We can only have 99 callbacks, because MultipathPolicyTracker is
4352 // already one of them.
4353 final int MAX_REQUESTS = 99;
4354 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004355 final int INTENTS = 10;
4356 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4357
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004358 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004359 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004360
Hugo Benichi893a7622017-09-29 09:34:08 +09004361 int j = 0;
4362 while (j++ < CALLBACKS / 2) {
4363 NetworkCallback cb = new NetworkCallback();
4364 mCm.requestNetwork(networkRequest, cb);
4365 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004366 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004367 while (j++ < CALLBACKS) {
4368 NetworkCallback cb = new NetworkCallback();
4369 mCm.registerNetworkCallback(networkRequest, cb);
4370 registered.add(cb);
4371 }
4372 j = 0;
4373 while (j++ < INTENTS / 2) {
4374 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4375 mCm.requestNetwork(networkRequest, pi);
4376 registered.add(pi);
4377 }
4378 while (j++ < INTENTS) {
4379 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4380 mCm.registerNetworkCallback(networkRequest, pi);
4381 registered.add(pi);
4382 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004383
Hugo Benichi893a7622017-09-29 09:34:08 +09004384 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004385 assertThrows(TooManyRequestsException.class, () ->
4386 mCm.requestNetwork(networkRequest, new NetworkCallback())
4387 );
4388 assertThrows(TooManyRequestsException.class, () ->
4389 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4390 );
4391 assertThrows(TooManyRequestsException.class, () ->
4392 mCm.requestNetwork(networkRequest,
4393 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4394 );
4395 assertThrows(TooManyRequestsException.class, () ->
4396 mCm.registerNetworkCallback(networkRequest,
4397 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4398 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004399
Hugo Benichi893a7622017-09-29 09:34:08 +09004400 for (Object o : registered) {
4401 if (o instanceof NetworkCallback) {
4402 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004403 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004404 if (o instanceof PendingIntent) {
4405 mCm.unregisterNetworkCallback((PendingIntent)o);
4406 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004407 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004408 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004409
4410 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4411 for (int i = 0; i < MAX_REQUESTS; i++) {
4412 NetworkCallback networkCallback = new NetworkCallback();
4413 mCm.requestNetwork(networkRequest, networkCallback);
4414 mCm.unregisterNetworkCallback(networkCallback);
4415 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004416 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004417
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004418 for (int i = 0; i < MAX_REQUESTS; i++) {
4419 NetworkCallback networkCallback = new NetworkCallback();
4420 mCm.registerNetworkCallback(networkRequest, networkCallback);
4421 mCm.unregisterNetworkCallback(networkCallback);
4422 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004423 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004424
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004425 for (int i = 0; i < MAX_REQUESTS; i++) {
4426 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004427 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004428 mCm.requestNetwork(networkRequest, pendingIntent);
4429 mCm.unregisterNetworkCallback(pendingIntent);
4430 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004431 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004432
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004433 for (int i = 0; i < MAX_REQUESTS; i++) {
4434 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004435 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004436 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4437 mCm.unregisterNetworkCallback(pendingIntent);
4438 }
4439 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004440
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004441 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004442 public void testNetworkInfoOfTypeNone() throws Exception {
Chalard Jean407deb72019-11-19 16:14:30 +09004443 ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004444
4445 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004446 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004447 assertNull(mCm.getActiveNetworkInfo());
4448
4449 Network[] allNetworks = mCm.getAllNetworks();
4450 assertLength(1, allNetworks);
4451 Network network = allNetworks[0];
4452 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4453 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4454
4455 final NetworkRequest request =
4456 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4457 final TestNetworkCallback callback = new TestNetworkCallback();
4458 mCm.registerNetworkCallback(request, callback);
4459
Hugo Benichic1014502017-07-19 10:10:52 +09004460 // Bring up wifi aware network.
lucaslin783f2212019-10-22 18:27:33 +08004461 wifiAware.connect(false, false, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004462 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004463
4464 assertNull(mCm.getActiveNetworkInfo());
4465 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004466 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004467 // of this test. Fix it and uncomment the assert below.
4468 //assertEmpty(mCm.getAllNetworkInfo());
4469
Hugo Benichic1014502017-07-19 10:10:52 +09004470 // Disconnect wifi aware network.
4471 wifiAware.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09004472 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004473 mCm.unregisterNetworkCallback(callback);
4474
4475 verifyNoNetwork();
4476 if (broadcastCV.block(10)) {
4477 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4478 }
4479 }
4480
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004481 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004482 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4483 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4484 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4485 assertNull(mCm.getNetworkForType(TYPE_NONE));
4486 assertNull(mCm.getLinkProperties(TYPE_NONE));
4487 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4488
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004489 assertThrows(IllegalArgumentException.class,
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004490 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004491
4492 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004493 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4494 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004495 // TODO: let test context have configuration application target sdk version
4496 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004497 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4498 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4499 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004500 }
4501
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004502 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004503 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004504 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4505 .addTransportType(TRANSPORT_WIFI).build();
4506 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4507 mCm.registerNetworkCallback(networkRequest, networkCallback);
4508
4509 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004510 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004511 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4512 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4513 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4514 lp.addLinkAddress(myIpv4Address);
4515 lp.addRoute(myIpv4DefaultRoute);
4516
4517 // Verify direct routes are added when network agent is first registered in
4518 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004519 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004520 networkAgent.connect(true);
Chalard Jean059c4262019-09-30 17:51:12 +09004521 networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
4522 networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
4523 CallbackEntry.LinkPropertiesChanged cbi =
4524 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004525 networkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004526 networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004527 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4528 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004529 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004530 Arrays.asList(myIpv4DefaultRoute));
4531 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4532 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4533
4534 // Verify direct routes are added during subsequent link properties updates.
4535 LinkProperties newLp = new LinkProperties(lp);
4536 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4537 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4538 newLp.addLinkAddress(myIpv6Address1);
4539 newLp.addLinkAddress(myIpv6Address2);
4540 networkAgent.sendLinkProperties(newLp);
Chalard Jean059c4262019-09-30 17:51:12 +09004541 cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004542 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004543 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004544 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4545 Arrays.asList(myIpv4DefaultRoute));
4546 mCm.unregisterNetworkCallback(networkCallback);
4547 }
4548
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004549 @Test
4550 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004551 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4552 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004553
Varun Anandd33cbc62019-02-07 14:13:13 -08004554 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4555 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4556
4557 LinkProperties cellLp = new LinkProperties();
4558 cellLp.setInterfaceName(MOBILE_IFNAME);
4559 LinkProperties wifiLp = new LinkProperties();
4560 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004561
4562 // Simple connection should have updated ifaces
4563 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004564 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004565 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004566 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004567 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4568 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004569 reset(mStatsService);
4570
4571 // Default network switch should update ifaces.
4572 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004573 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004574 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004575 assertEquals(wifiLp, mService.getActiveLinkProperties());
4576 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004577 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4578 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004579 reset(mStatsService);
4580
4581 // Disconnect should update ifaces.
4582 mWiFiNetworkAgent.disconnect();
4583 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004584 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004585 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4586 eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004587 reset(mStatsService);
4588
4589 // Metered change should update ifaces
4590 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4591 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004592 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004593 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4594 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004595 reset(mStatsService);
4596
4597 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4598 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004599 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004600 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4601 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004602 reset(mStatsService);
4603
4604 // Captive portal change shouldn't update ifaces
4605 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4606 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004607 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004608 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4609 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004610 reset(mStatsService);
4611
4612 // Roaming change should update ifaces
4613 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4614 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004615 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004616 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4617 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004618 reset(mStatsService);
4619 }
4620
Erik Klinee89953b2018-01-11 16:11:10 +09004621 @Test
4622 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004623 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004624
4625 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004626 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004627
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004628 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09004629 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004630 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004631 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004632
4633 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004634 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004635 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4636 // "is-reachable" testing in order to not program netd with unreachable
4637 // nameservers that it might try repeated to validate.
4638 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004639 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4640 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004641 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004642 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4643 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004644 mCellNetworkAgent.sendLinkProperties(cellLp);
4645 mCellNetworkAgent.connect(false);
4646 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004647
4648 verify(mMockDnsResolver, times(1)).createNetworkCache(
4649 eq(mCellNetworkAgent.getNetwork().netId));
4650 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004651 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004652 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004653
4654 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4655 mCellNetworkAgent.sendLinkProperties(cellLp);
4656 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004657 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004658 mResolverParamsParcelCaptor.capture());
4659 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4660 assertEquals(1, resolvrParams.servers.length);
4661 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004662 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004663 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004664 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004665
4666 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4667 mCellNetworkAgent.sendLinkProperties(cellLp);
4668 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004669 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004670 mResolverParamsParcelCaptor.capture());
4671 resolvrParams = mResolverParamsParcelCaptor.getValue();
4672 assertEquals(2, resolvrParams.servers.length);
4673 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004674 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004675 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004676 assertEquals(2, resolvrParams.tlsServers.length);
4677 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004678 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004679 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004680
4681 final String TLS_SPECIFIER = "tls.example.com";
4682 final String TLS_SERVER6 = "2001:db8:53::53";
4683 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4684 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004685 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4686 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4687
Erik Kline117e7f32018-03-04 21:01:01 +09004688 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004689 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004690 mResolverParamsParcelCaptor.capture());
4691 resolvrParams = mResolverParamsParcelCaptor.getValue();
4692 assertEquals(2, resolvrParams.servers.length);
4693 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004694 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004695 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004696 }
4697
Erik Kline79c6d052018-03-21 07:18:33 -07004698 @Test
lucaslin783f2212019-10-22 18:27:33 +08004699 public void testPrivateDnsNotification() throws Exception {
4700 NetworkRequest request = new NetworkRequest.Builder()
4701 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4702 .build();
4703 TestNetworkCallback callback = new TestNetworkCallback();
4704 mCm.registerNetworkCallback(request, callback);
4705 // Bring up wifi.
4706 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4707 mWiFiNetworkAgent.connect(false);
4708 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4709 // Private DNS resolution failed, checking if the notification will be shown or not.
4710 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4711 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4712 waitForIdle();
4713 // If network validation failed, NetworkMonitor will re-evaluate the network.
4714 // ConnectivityService should filter the redundant notification. This part is trying to
4715 // simulate that situation and check if ConnectivityService could filter that case.
4716 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4717 waitForIdle();
4718 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
4719 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4720 // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
4721 // shown.
4722 mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
4723 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4724 waitForIdle();
4725 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
4726 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
4727 // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
4728 // shown again.
4729 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4730 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4731 waitForIdle();
4732 verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
4733 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4734 }
4735
4736 @Test
Erik Kline79c6d052018-03-21 07:18:33 -07004737 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004738 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004739 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004740
4741 // The default on Android is opportunistic mode ("Automatic").
4742 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4743
dalyk1fcb7392018-03-05 12:42:22 -05004744 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4745 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4746 .addTransportType(TRANSPORT_CELLULAR).build();
4747 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4748
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004749 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07004750 waitForIdle();
4751 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004752 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004753 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004754
4755 final LinkProperties cellLp = new LinkProperties();
4756 cellLp.setInterfaceName(MOBILE_IFNAME);
4757 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4758 // "is-reachable" testing in order to not program netd with unreachable
4759 // nameservers that it might try repeated to validate.
4760 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4761 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4762 MOBILE_IFNAME));
4763 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4764 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4765 MOBILE_IFNAME));
4766 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4767 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4768
4769 mCellNetworkAgent.sendLinkProperties(cellLp);
4770 mCellNetworkAgent.connect(false);
4771 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004772 verify(mMockDnsResolver, times(1)).createNetworkCache(
4773 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08004774 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004775 mResolverParamsParcelCaptor.capture());
4776 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4777 assertEquals(2, resolvrParams.tlsServers.length);
4778 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004779 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07004780 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004781 assertEquals(2, resolvrParams.tlsServers.length);
4782 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004783 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004784 reset(mMockDnsResolver);
Chalard Jean059c4262019-09-30 17:51:12 +09004785 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
4786 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004787 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004788 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4789 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4790 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004791 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004792 assertFalse(cbi.getLp().isPrivateDnsActive());
4793 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004794
4795 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004796 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004797 mResolverParamsParcelCaptor.capture());
4798 resolvrParams = mResolverParamsParcelCaptor.getValue();
4799 assertEquals(2, resolvrParams.servers.length);
4800 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004801 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004802 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004803 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004804
4805 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004806 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004807 mResolverParamsParcelCaptor.capture());
4808 resolvrParams = mResolverParamsParcelCaptor.getValue();
4809 assertEquals(2, resolvrParams.servers.length);
4810 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004811 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08004812 assertEquals(2, resolvrParams.tlsServers.length);
4813 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004814 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004815 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004816 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004817
dalyk1fcb7392018-03-05 12:42:22 -05004818 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4819 // Can't test dns configuration for strict mode without properly mocking
4820 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean059c4262019-09-30 17:51:12 +09004821 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004822 mCellNetworkAgent);
4823 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004824 assertTrue(cbi.getLp().isPrivateDnsActive());
4825 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004826 }
4827
4828 @Test
4829 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4830 // The default on Android is opportunistic mode ("Automatic").
4831 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4832
4833 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4834 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4835 .addTransportType(TRANSPORT_CELLULAR).build();
4836 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4837
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004838 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05004839 waitForIdle();
4840 LinkProperties lp = new LinkProperties();
4841 mCellNetworkAgent.sendLinkProperties(lp);
4842 mCellNetworkAgent.connect(false);
4843 waitForIdle();
Chalard Jean059c4262019-09-30 17:51:12 +09004844 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
4845 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004846 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004847 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4848 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4849 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004850 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004851 assertFalse(cbi.getLp().isPrivateDnsActive());
4852 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004853 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004854 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004855
4856 // Send a validation event for a server that is not part of the current
4857 // resolver config. The validation event should be ignored.
4858 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4859 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4860 cellNetworkCallback.assertNoCallback();
4861
4862 // Add a dns server to the LinkProperties.
4863 LinkProperties lp2 = new LinkProperties(lp);
4864 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4865 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean059c4262019-09-30 17:51:12 +09004866 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004867 mCellNetworkAgent);
4868 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004869 assertFalse(cbi.getLp().isPrivateDnsActive());
4870 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004871 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004872 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004873
4874 // Send a validation event containing a hostname that is not part of
4875 // the current resolver config. The validation event should be ignored.
4876 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4877 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4878 cellNetworkCallback.assertNoCallback();
4879
4880 // Send a validation event where validation failed.
4881 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4882 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4883 cellNetworkCallback.assertNoCallback();
4884
4885 // Send a validation event where validation succeeded for a server in
4886 // the current resolver config. A LinkProperties callback with updated
4887 // private dns fields should be sent.
4888 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4889 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean059c4262019-09-30 17:51:12 +09004890 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004891 mCellNetworkAgent);
4892 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004893 assertTrue(cbi.getLp().isPrivateDnsActive());
4894 assertNull(cbi.getLp().getPrivateDnsServerName());
4895 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004896
4897 // The private dns fields in LinkProperties should be preserved when
4898 // the network agent sends unrelated changes.
4899 LinkProperties lp3 = new LinkProperties(lp2);
4900 lp3.setMtu(1300);
4901 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean059c4262019-09-30 17:51:12 +09004902 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004903 mCellNetworkAgent);
4904 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004905 assertTrue(cbi.getLp().isPrivateDnsActive());
4906 assertNull(cbi.getLp().getPrivateDnsServerName());
4907 checkDnsServers(cbi.getLp(), dnsServers);
4908 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05004909
4910 // Removing the only validated server should affect the private dns
4911 // fields in LinkProperties.
4912 LinkProperties lp4 = new LinkProperties(lp3);
4913 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4914 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean059c4262019-09-30 17:51:12 +09004915 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004916 mCellNetworkAgent);
4917 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004918 assertFalse(cbi.getLp().isPrivateDnsActive());
4919 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004920 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004921 checkDnsServers(cbi.getLp(), dnsServers);
4922 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07004923 }
4924
Rubin Xu1bb5c082017-09-05 18:40:49 +01004925 private void checkDirectlyConnectedRoutes(Object callbackObj,
4926 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4927 assertTrue(callbackObj instanceof LinkProperties);
4928 LinkProperties lp = (LinkProperties) callbackObj;
4929
4930 Set<RouteInfo> expectedRoutes = new ArraySet<>();
4931 expectedRoutes.addAll(otherRoutes);
4932 for (LinkAddress address : linkAddresses) {
4933 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4934 // Duplicates in linkAddresses are considered failures
4935 assertTrue(expectedRoutes.add(localRoute));
4936 }
4937 List<RouteInfo> observedRoutes = lp.getRoutes();
4938 assertEquals(expectedRoutes.size(), observedRoutes.size());
4939 assertTrue(observedRoutes.containsAll(expectedRoutes));
4940 }
4941
dalyk1fcb7392018-03-05 12:42:22 -05004942 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4943 assertTrue(callbackObj instanceof LinkProperties);
4944 LinkProperties lp = (LinkProperties) callbackObj;
4945 assertEquals(dnsServers.size(), lp.getDnsServers().size());
4946 assertTrue(lp.getDnsServers().containsAll(dnsServers));
4947 }
4948
Chalard Jean0b214af2018-01-12 17:22:49 +09004949 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004950 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09004951 final int uid = Process.myUid();
4952
4953 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004954 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004955 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4956 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004957 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004958 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4959 final NetworkRequest genericRequest = new NetworkRequest.Builder()
4960 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09004961 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4962 .addTransportType(TRANSPORT_WIFI).build();
4963 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09004964 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09004965 .addTransportType(TRANSPORT_VPN).build();
4966 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09004967 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004968 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4969 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004970 mCm.registerDefaultNetworkCallback(defaultCallback);
4971 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004972
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004973 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09004974 mWiFiNetworkAgent.connect(false);
4975
4976 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004977 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004978 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004979 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004980 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004981 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004982
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004983 final TestNetworkAgentWrapper
4984 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean0b214af2018-01-12 17:22:49 +09004985 final ArraySet<UidRange> ranges = new ArraySet<>();
4986 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004987 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4988 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004989 // VPN networks do not satisfy the default request and are automatically validated
4990 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004991 assertFalse(NetworkMonitorUtils.isValidationRequired(
4992 vpnNetworkAgent.getNetworkCapabilities()));
lucaslin783f2212019-10-22 18:27:33 +08004993 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004994
Chalard Jean0b214af2018-01-12 17:22:49 +09004995 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004996 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004997 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09004998
4999 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005000 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005001 wifiNetworkCallback.assertNoCallback();
5002 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005003 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5004 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005005
Chalard Jean059c4262019-09-30 17:51:12 +09005006 genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005007 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005008 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
Chalard Jean059c4262019-09-30 17:51:12 +09005009 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005010 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005011
5012 ranges.clear();
5013 vpnNetworkAgent.setUids(ranges);
5014
Chalard Jean059c4262019-09-30 17:51:12 +09005015 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005016 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005017 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005018 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005019
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005020 // TODO : The default network callback should actually get a LOST call here (also see the
5021 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5022 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5023 // can't currently update their UIDs without disconnecting, so this does not matter too
5024 // much, but that is the reason the test here has to check for an update to the
5025 // capabilities instead of the expected LOST then AVAILABLE.
Chalard Jean059c4262019-09-30 17:51:12 +09005026 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005027
Chalard Jean0b214af2018-01-12 17:22:49 +09005028 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005029 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005030 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005031
5032 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005033 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005034 wifiNetworkCallback.assertNoCallback();
5035 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005036 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5037 // happen outside of the test, ConnectivityService does not rematch callbacks.
Chalard Jean059c4262019-09-30 17:51:12 +09005038 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005039
5040 mWiFiNetworkAgent.disconnect();
5041
Chalard Jean059c4262019-09-30 17:51:12 +09005042 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5043 genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5044 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005045 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005046 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005047
5048 vpnNetworkAgent.disconnect();
5049
Chalard Jean059c4262019-09-30 17:51:12 +09005050 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005051 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005052 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005053 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5054 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005055 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005056
5057 mCm.unregisterNetworkCallback(genericNetworkCallback);
5058 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5059 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005060 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005061 }
Chalard Jean26400492018-04-18 20:18:38 +09005062
5063 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005064 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09005065 final int uid = Process.myUid();
5066
5067 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5068 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005069
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005070 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09005071 mWiFiNetworkAgent.connect(true);
5072
5073 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5074 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5075
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005076 TestNetworkAgentWrapper
5077 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09005078 final ArraySet<UidRange> ranges = new ArraySet<>();
5079 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005080 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5081 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005082 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5083 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005084 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005085
5086 defaultCallback.assertNoCallback();
5087 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5088
5089 vpnNetworkAgent.disconnect();
5090 defaultCallback.assertNoCallback();
5091
Varun Anand4fa80e82019-02-06 10:13:38 -08005092 mCm.unregisterNetworkCallback(defaultCallback);
5093 }
5094
5095 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005096 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005097 final int uid = Process.myUid();
5098
5099 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5100 mCm.registerDefaultNetworkCallback(defaultCallback);
5101
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005102 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005103 mWiFiNetworkAgent.connect(true);
5104
5105 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5106 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5107
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005108 TestNetworkAgentWrapper
5109 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005110 final ArraySet<UidRange> ranges = new ArraySet<>();
5111 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005112 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5113 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005114 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
5115 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005116 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005117
Chalard Jean26400492018-04-18 20:18:38 +09005118 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5119 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5120
5121 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005122 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean26400492018-04-18 20:18:38 +09005123 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5124
Chalard Jean26400492018-04-18 20:18:38 +09005125 mCm.unregisterNetworkCallback(defaultCallback);
5126 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005127
5128 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005129 public void testVpnUnvalidated() throws Exception {
5130 final TestNetworkCallback callback = new TestNetworkCallback();
5131 mCm.registerDefaultNetworkCallback(callback);
5132
5133 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005134 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005135 mEthernetNetworkAgent.connect(true);
5136 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5137 callback.assertNoCallback();
5138
5139 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5140 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005141 final TestNetworkAgentWrapper
5142 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005143 final ArraySet<UidRange> ranges = new ArraySet<>();
5144 ranges.add(new UidRange(uid, uid));
5145 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5146 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005147 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
5148 false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005149 mMockVpn.connect();
5150
5151 // Even though the VPN is unvalidated, it becomes the default network for our app.
5152 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5153 // TODO: this looks like a spurious callback.
Chalard Jean059c4262019-09-30 17:51:12 +09005154 callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005155 callback.assertNoCallback();
5156
5157 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5158 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5159 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5160
5161 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5162 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5163 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5164
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005165 assertFalse(NetworkMonitorUtils.isValidationRequired(
5166 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005167 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005168 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005169
5170 // Pretend that the VPN network validates.
lucaslin783f2212019-10-22 18:27:33 +08005171 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005172 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5173 // Expect to see the validated capability, but no other changes, because the VPN is already
5174 // the default network for the app.
5175 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5176 callback.assertNoCallback();
5177
5178 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005179 callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005180 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5181 }
5182
5183 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005184 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005185 final int uid = Process.myUid();
5186
5187 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5188 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5189 .removeCapability(NET_CAPABILITY_NOT_VPN)
5190 .addTransportType(TRANSPORT_VPN)
5191 .build();
5192 NetworkCapabilities nc;
5193 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5194 vpnNetworkCallback.assertNoCallback();
5195
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005196 final TestNetworkAgentWrapper
5197 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005198 final ArraySet<UidRange> ranges = new ArraySet<>();
5199 ranges.add(new UidRange(uid, uid));
5200 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5201 mMockVpn.connect();
5202 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005203 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5204 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005205
5206 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5207 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5208 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5209 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5210 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5211 // For safety reasons a VPN without underlying networks is considered metered.
5212 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5213
5214 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005215 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005216 mCellNetworkAgent.connect(true);
5217
5218 mService.setUnderlyingNetworksForVpn(
5219 new Network[] { mCellNetworkAgent.getNetwork() });
5220
Chalard Jean6f4216f2019-06-05 01:40:32 +09005221 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5222 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005223 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005224 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005225
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005226 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005227 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5228 mWiFiNetworkAgent.connect(true);
5229
5230 mService.setUnderlyingNetworksForVpn(
5231 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5232
Chalard Jean6f4216f2019-06-05 01:40:32 +09005233 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5234 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005235 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005236 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005237
5238 // Don't disconnect, but note the VPN is not using wifi any more.
5239 mService.setUnderlyingNetworksForVpn(
5240 new Network[] { mCellNetworkAgent.getNetwork() });
5241
Chalard Jean6f4216f2019-06-05 01:40:32 +09005242 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5243 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005244 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005245 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005246
5247 // Use Wifi but not cell. Note the VPN is now unmetered.
5248 mService.setUnderlyingNetworksForVpn(
5249 new Network[] { mWiFiNetworkAgent.getNetwork() });
5250
Chalard Jean6f4216f2019-06-05 01:40:32 +09005251 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5252 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005253 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005254 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005255
5256 // Use both again.
5257 mService.setUnderlyingNetworksForVpn(
5258 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5259
Chalard Jean6f4216f2019-06-05 01:40:32 +09005260 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5261 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005262 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005263 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005264
Chalard Jean6b65ec72018-05-18 22:02:56 +09005265 // Disconnect cell. Receive update without even removing the dead network from the
5266 // underlying networks – it's dead anyway. Not metered any more.
5267 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005268 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5269 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005270 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005271 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005272
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005273 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005274 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005275 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5276 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005277 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005278 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005279
5280 mMockVpn.disconnect();
5281 }
junyulai4a192e22018-06-13 15:00:37 +08005282
Mike Yuf9729752018-08-17 15:22:05 +08005283 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005284 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005285 final int uid = Process.myUid();
5286
5287 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5288 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5289 .removeCapability(NET_CAPABILITY_NOT_VPN)
5290 .addTransportType(TRANSPORT_VPN)
5291 .build();
5292 NetworkCapabilities nc;
5293 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5294 vpnNetworkCallback.assertNoCallback();
5295
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005296 final TestNetworkAgentWrapper
5297 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005298 final ArraySet<UidRange> ranges = new ArraySet<>();
5299 ranges.add(new UidRange(uid, uid));
5300 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5301 mMockVpn.connect();
5302 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005303 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5304 false /* isStrictMode */);
Varun Anand4fa80e82019-02-06 10:13:38 -08005305
5306 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5307 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5308 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5309 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5310 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5311 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5312 // In case of no default network, VPN is considered metered.
5313 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5314
5315 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005316 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005317 mCellNetworkAgent.connect(true);
5318
Chalard Jean6f4216f2019-06-05 01:40:32 +09005319 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5320 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005321 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005322 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005323
5324 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005325 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005326 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5327 mWiFiNetworkAgent.connect(true);
5328
Chalard Jean6f4216f2019-06-05 01:40:32 +09005329 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5330 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005331 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005332 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005333
5334 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5335 // the capabilities.
5336 mCellNetworkAgent.disconnect();
5337
5338 // Disconnect wifi too. Now we have no default network.
5339 mWiFiNetworkAgent.disconnect();
5340
Chalard Jean6f4216f2019-06-05 01:40:32 +09005341 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5342 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005343 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005344 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005345
5346 mMockVpn.disconnect();
5347 }
5348
5349 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005350 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005351 // Returns true by default when no network is available.
5352 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005353 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005354 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5355 mWiFiNetworkAgent.connect(true);
5356 waitForIdle();
5357
5358 assertFalse(mCm.isActiveNetworkMetered());
5359 }
5360
5361 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005362 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005363 // Returns true by default when no network is available.
5364 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005365 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005366 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5367 mCellNetworkAgent.connect(true);
5368 waitForIdle();
5369
5370 assertTrue(mCm.isActiveNetworkMetered());
5371 }
5372
5373 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005374 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005375 // Returns true by default when no network is available.
5376 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005377 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005378 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5379 mCellNetworkAgent.connect(true);
5380 waitForIdle();
5381 assertTrue(mCm.isActiveNetworkMetered());
5382
5383 // Connect VPN network. By default it is using current default network (Cell).
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005384 TestNetworkAgentWrapper
5385 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005386 final ArraySet<UidRange> ranges = new ArraySet<>();
5387 final int uid = Process.myUid();
5388 ranges.add(new UidRange(uid, uid));
5389 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5390 mMockVpn.setUids(ranges);
5391 vpnNetworkAgent.connect(true);
5392 mMockVpn.connect();
5393 waitForIdle();
5394 // Ensure VPN is now the active network.
5395 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5396
5397 // Expect VPN to be metered.
5398 assertTrue(mCm.isActiveNetworkMetered());
5399
5400 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005401 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005402 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5403 mWiFiNetworkAgent.connect(true);
5404 waitForIdle();
5405 // VPN should still be the active network.
5406 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5407
5408 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5409 assertFalse(mCm.isActiveNetworkMetered());
5410
5411 // Disconnecting Cell should not affect VPN's meteredness.
5412 mCellNetworkAgent.disconnect();
5413 waitForIdle();
5414
5415 assertFalse(mCm.isActiveNetworkMetered());
5416
5417 // Disconnect WiFi; Now there is no platform default network.
5418 mWiFiNetworkAgent.disconnect();
5419 waitForIdle();
5420
5421 // VPN without any underlying networks is treated as metered.
5422 assertTrue(mCm.isActiveNetworkMetered());
5423
5424 vpnNetworkAgent.disconnect();
5425 mMockVpn.disconnect();
5426 }
5427
5428 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005429 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005430 // Returns true by default when no network is available.
5431 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005432 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005433 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5434 mCellNetworkAgent.connect(true);
5435 waitForIdle();
5436 assertTrue(mCm.isActiveNetworkMetered());
5437
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005438 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005439 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5440 mWiFiNetworkAgent.connect(true);
5441 waitForIdle();
5442 assertFalse(mCm.isActiveNetworkMetered());
5443
5444 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005445 TestNetworkAgentWrapper
5446 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005447 final ArraySet<UidRange> ranges = new ArraySet<>();
5448 final int uid = Process.myUid();
5449 ranges.add(new UidRange(uid, uid));
5450 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5451 mMockVpn.setUids(ranges);
5452 vpnNetworkAgent.connect(true);
5453 mMockVpn.connect();
5454 waitForIdle();
5455 // Ensure VPN is now the active network.
5456 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5457 // VPN is using Cell
5458 mService.setUnderlyingNetworksForVpn(
5459 new Network[] { mCellNetworkAgent.getNetwork() });
5460 waitForIdle();
5461
5462 // Expect VPN to be metered.
5463 assertTrue(mCm.isActiveNetworkMetered());
5464
5465 // VPN is now using WiFi
5466 mService.setUnderlyingNetworksForVpn(
5467 new Network[] { mWiFiNetworkAgent.getNetwork() });
5468 waitForIdle();
5469
5470 // Expect VPN to be unmetered
5471 assertFalse(mCm.isActiveNetworkMetered());
5472
5473 // VPN is using Cell | WiFi.
5474 mService.setUnderlyingNetworksForVpn(
5475 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5476 waitForIdle();
5477
5478 // Expect VPN to be metered.
5479 assertTrue(mCm.isActiveNetworkMetered());
5480
5481 // VPN is using WiFi | Cell.
5482 mService.setUnderlyingNetworksForVpn(
5483 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5484 waitForIdle();
5485
5486 // Order should not matter and VPN should still be metered.
5487 assertTrue(mCm.isActiveNetworkMetered());
5488
5489 // VPN is not using any underlying networks.
5490 mService.setUnderlyingNetworksForVpn(new Network[0]);
5491 waitForIdle();
5492
5493 // VPN without underlying networks is treated as metered.
5494 assertTrue(mCm.isActiveNetworkMetered());
5495
5496 vpnNetworkAgent.disconnect();
5497 mMockVpn.disconnect();
5498 }
5499
5500 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005501 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005502 // Returns true by default when no network is available.
5503 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005504 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005505 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5506 mWiFiNetworkAgent.connect(true);
5507 waitForIdle();
5508 assertFalse(mCm.isActiveNetworkMetered());
5509
5510 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005511 TestNetworkAgentWrapper
5512 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005513 final ArraySet<UidRange> ranges = new ArraySet<>();
5514 final int uid = Process.myUid();
5515 ranges.add(new UidRange(uid, uid));
5516 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5517 mMockVpn.setUids(ranges);
5518 vpnNetworkAgent.connect(true);
5519 mMockVpn.connectAsAlwaysMetered();
5520 waitForIdle();
5521 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5522
5523 // VPN is tracking current platform default (WiFi).
5524 mService.setUnderlyingNetworksForVpn(null);
5525 waitForIdle();
5526
5527 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5528 assertTrue(mCm.isActiveNetworkMetered());
5529
5530 // VPN explicitly declares WiFi as its underlying network.
5531 mService.setUnderlyingNetworksForVpn(
5532 new Network[] { mWiFiNetworkAgent.getNetwork() });
5533 waitForIdle();
5534
5535 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5536 assertTrue(mCm.isActiveNetworkMetered());
5537
5538 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5539 // anyways suppose to be metered.
5540 mWiFiNetworkAgent.disconnect();
5541 waitForIdle();
5542
5543 assertTrue(mCm.isActiveNetworkMetered());
5544
5545 vpnNetworkAgent.disconnect();
5546 }
5547
5548 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005549 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005550 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5551 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5552 .addTransportType(TRANSPORT_CELLULAR)
5553 .build();
5554 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5555
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005556 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005557 mCellNetworkAgent.connect(true);
5558 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5559
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005560 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08005561 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5562
5563 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005564 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005565 cellNetworkCallback.assertNoCallback();
5566
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005567 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005568 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5569
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005570 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005571 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5572
5573 // Restrict the network based on UID rule and NOT_METERED capability change.
5574 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5575 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5576 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5577 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5578 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5579 mCellNetworkAgent);
5580 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005581 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005582 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5583
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005584 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005585 cellNetworkCallback.assertNoCallback();
5586
5587 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005588 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005589 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005590 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005591 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005592 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005593 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5594 cellNetworkCallback.assertNoCallback();
5595
5596 mCm.unregisterNetworkCallback(cellNetworkCallback);
5597 }
5598
5599 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005600 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005601 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5602 mCm.registerDefaultNetworkCallback(defaultCallback);
5603
5604 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005605 setUidRulesChanged(RULE_REJECT_ALL);
5606 setUidRulesChanged(RULE_NONE);
5607 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005608 defaultCallback.assertNoCallback();
5609
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005610 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005611 mCellNetworkAgent.connect(true);
5612 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5613 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5614
5615 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005616 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08005617 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5618 mWiFiNetworkAgent.connect(true);
5619 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5620
5621 // Switch to METERED network. Restrict the use of the network.
5622 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005623 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005624 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5625
5626 // Network becomes NOT_METERED.
5627 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5628 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5629 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5630
5631 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005632 setRestrictBackgroundChanged(true);
5633 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005634 defaultCallback.assertNoCallback();
5635
5636 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005637 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005638 defaultCallback.assertNoCallback();
5639
5640 mCm.unregisterNetworkCallback(defaultCallback);
5641 }
5642
junyulai4a192e22018-06-13 15:00:37 +08005643 /**
5644 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5645 */
5646 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5647 InterfaceConfiguration cfg = new InterfaceConfiguration();
5648 cfg.setHardwareAddress("11:22:33:44:55:66");
5649 cfg.setLinkAddress(la);
5650 return cfg;
5651 }
5652
5653 /**
5654 * Make expected stack link properties, copied from Nat464Xlat.
5655 */
5656 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5657 LinkAddress clatAddress = la;
5658 LinkProperties stacked = new LinkProperties();
5659 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5660 RouteInfo ipv4Default = new RouteInfo(
5661 new LinkAddress(Inet4Address.ANY, 0),
5662 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5663 stacked.addRoute(ipv4Default);
5664 stacked.addLinkAddress(clatAddress);
5665 return stacked;
5666 }
5667
5668 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005669 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08005670 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5671 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005672 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5673 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5674
junyulai4a192e22018-06-13 15:00:37 +08005675 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5676 .addTransportType(TRANSPORT_CELLULAR)
5677 .addCapability(NET_CAPABILITY_INTERNET)
5678 .build();
5679 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5680 mCm.registerNetworkCallback(networkRequest, networkCallback);
5681
Lorenzo Colittid593e292019-02-19 13:21:56 +09005682 // Prepare ipv6 only link properties.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005683 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005684 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
junyulai4a192e22018-06-13 15:00:37 +08005685 final LinkProperties cellLp = new LinkProperties();
5686 cellLp.setInterfaceName(MOBILE_IFNAME);
5687 cellLp.addLinkAddress(myIpv6);
5688 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5689 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
5690 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005691 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005692 reset(mMockNetd);
junyulai4a192e22018-06-13 15:00:37 +08005693 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5694 .thenReturn(getClatInterfaceConfig(myIpv4));
5695
Lorenzo Colittid593e292019-02-19 13:21:56 +09005696 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005697 mCellNetworkAgent.sendLinkProperties(cellLp);
5698 mCellNetworkAgent.connect(true);
Luke Huanga24d5d82019-04-09 18:41:49 +08005699
5700 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
5701 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
5702
junyulai4a192e22018-06-13 15:00:37 +08005703 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005704 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005705
Lorenzo Colittid593e292019-02-19 13:21:56 +09005706 // Switching default network updates TCP buffer sizes.
5707 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5708
5709 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5710 // the NAT64 prefix was removed because one was never discovered.
5711 cellLp.addLinkAddress(myIpv4);
5712 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005713 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005714 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005715 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005716
5717 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005718 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005719 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005720 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005721
5722 // Remove IPv4 address. Expect prefix discovery to be started again.
5723 cellLp.removeLinkAddress(myIpv4);
5724 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5725 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005726 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005727 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005728
5729 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005730 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005731 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005732 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5733 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005734 LinkProperties lpBeforeClat = networkCallback.expectCallback(
Chalard Jean059c4262019-09-30 17:51:12 +09005735 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005736 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5737 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5738 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5739
5740 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005741 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean059c4262019-09-30 17:51:12 +09005742 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005743 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5744 .getStackedLinks();
5745 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5746
5747 // Change trivial linkproperties and see if stacked link is preserved.
5748 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5749 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005750 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005751
5752 List<LinkProperties> stackedLpsAfterChange =
5753 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5754 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5755 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5756
Luke Huang65914772019-03-16 00:31:46 +08005757 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005758 mResolverParamsParcelCaptor.capture());
5759 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5760 assertEquals(1, resolvrParams.servers.length);
5761 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08005762
Lorenzo Colittid593e292019-02-19 13:21:56 +09005763 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5764 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005765 cellLp.addLinkAddress(myIpv4);
5766 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5767 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005768 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005769 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08005770 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005771
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005772 // As soon as stop is called, the linkproperties lose the stacked interface.
Chalard Jean059c4262019-09-30 17:51:12 +09005773 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005774 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
5775 LinkProperties expected = new LinkProperties(cellLp);
5776 expected.setNat64Prefix(kNat64Prefix);
5777 assertEquals(expected, actualLpAfterIpv4);
5778 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
5779
5780 // The interface removed callback happens but has no effect after stop is called.
5781 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5782 networkCallback.assertNoCallback();
5783
Lorenzo Colittid593e292019-02-19 13:21:56 +09005784 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005785 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005786 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005787 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005788
Lorenzo Colittid593e292019-02-19 13:21:56 +09005789 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5790 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5791 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005792 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5793 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005794
5795 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005796 cellLp.removeLinkAddress(myIpv4);
5797 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5798 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5799 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005800 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005801 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005802 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5803 kNat64PrefixString, 96);
Chalard Jean059c4262019-09-30 17:51:12 +09005804 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005805 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5806
Lorenzo Colittid593e292019-02-19 13:21:56 +09005807
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005808 // Clat iface comes up. Expect stacked link to be added.
5809 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005810 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5811 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005812
5813 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005814 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5815 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005816 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5817 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005818 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005819 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5820 (lp) -> lp.getStackedLinks().size() == 0);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005821
5822 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005823 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005824 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005825 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005826 mCm.unregisterNetworkCallback(networkCallback);
5827 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005828
5829 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005830 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08005831 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5832 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5833 .addCapability(NET_CAPABILITY_INTERNET)
5834 .build();
5835 mCm.registerNetworkCallback(networkRequest, networkCallback);
5836
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005837 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08005838 final LinkProperties cellLp = new LinkProperties();
5839 cellLp.setInterfaceName(MOBILE_IFNAME);
5840 mCellNetworkAgent.sendLinkProperties(cellLp);
5841 reset(mNetworkManagementService);
5842 mCellNetworkAgent.connect(true);
5843 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5844 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5845 eq(ConnectivityManager.TYPE_MOBILE));
5846
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005847 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005848 final LinkProperties wifiLp = new LinkProperties();
5849 wifiLp.setInterfaceName(WIFI_IFNAME);
5850 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5851
5852 // Network switch
5853 reset(mNetworkManagementService);
5854 mWiFiNetworkAgent.connect(true);
5855 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005856 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005857 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5858 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
5859 eq(ConnectivityManager.TYPE_WIFI));
5860 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
5861
5862 // Disconnect wifi and switch back to cell
5863 reset(mNetworkManagementService);
5864 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005865 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005866 assertNoCallbacks(networkCallback);
5867 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5868 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5869 eq(ConnectivityManager.TYPE_MOBILE));
5870
5871 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005872 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005873 wifiLp.setInterfaceName(WIFI_IFNAME);
5874 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5875 mWiFiNetworkAgent.connect(true);
5876 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005877 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005878 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5879
5880 // Disconnect cell
5881 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005882 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08005883 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005884 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005885 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
5886 // sent as network being switched. Ensure rule removal for cell will not be triggered
5887 // unexpectedly before network being removed.
5888 waitForIdle();
5889 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08005890 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
5891 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08005892 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08005893
5894 // Disconnect wifi
Chalard Jean407deb72019-11-19 16:14:30 +09005895 ConditionVariable cv = registerConnectivityBroadcast(1);
Chiachang Wanga6093042018-09-28 22:42:48 +08005896 reset(mNetworkManagementService);
5897 mWiFiNetworkAgent.disconnect();
5898 waitFor(cv);
5899 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5900
5901 // Clean up
5902 mCm.unregisterNetworkCallback(networkCallback);
5903 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005904
Chalard Jeane7b24752019-06-20 16:01:19 +09005905 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005906 String[] values = tcpBufferSizes.split(",");
5907 String rmemValues = String.join(" ", values[0], values[1], values[2]);
5908 String wmemValues = String.join(" ", values[3], values[4], values[5]);
Chalard Jeane7b24752019-06-20 16:01:19 +09005909 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005910 reset(mMockNetd);
5911 }
5912
5913 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005914 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005915 final String testTcpBufferSizes = "1,2,3,4,5,6";
paulhu66269b32019-08-30 19:24:36 +08005916 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5917 .addTransportType(TRANSPORT_CELLULAR)
5918 .addCapability(NET_CAPABILITY_INTERNET)
5919 .build();
5920 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5921 mCm.registerNetworkCallback(networkRequest, networkCallback);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005922
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005923 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005924 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005925 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005926 mCellNetworkAgent.connect(false);
paulhu66269b32019-08-30 19:24:36 +08005927 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005928 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5929
5930 // Change link Properties should have updated tcp buffer size.
5931 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005932 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005933 mCellNetworkAgent.sendLinkProperties(lp);
Chalard Jean059c4262019-09-30 17:51:12 +09005934 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005935 verifyTcpBufferSizeChange(testTcpBufferSizes);
paulhu66269b32019-08-30 19:24:36 +08005936
5937 // Clean up.
5938 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005939 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
paulhu66269b32019-08-30 19:24:36 +08005940 networkCallback.assertNoCallback();
5941 mCm.unregisterNetworkCallback(networkCallback);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005942 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005943
5944 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005945 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005946 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005947 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005948 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5949 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
5950 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
5951 }
5952
5953 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005954 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005955 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005956 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005957 mWiFiNetworkAgent.connect(true);
5958 waitForIdle();
5959 assertNull(mService.getProxyForNetwork(null));
5960
5961 final LinkProperties testLinkProperties = new LinkProperties();
5962 testLinkProperties.setHttpProxy(testProxyInfo);
5963
5964 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
5965 waitForIdle();
5966
5967 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
5968 }
5969
5970 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005971 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005972 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
5973
5974 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005975 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005976 mWiFiNetworkAgent.connect(true);
5977 waitForIdle();
5978 assertNull(mService.getProxyForNetwork(null));
5979
5980 // Set up a VPN network with a proxy
5981 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005982 final TestNetworkAgentWrapper
5983 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005984 final ArraySet<UidRange> ranges = new ArraySet<>();
5985 ranges.add(new UidRange(uid, uid));
5986 mMockVpn.setUids(ranges);
5987 LinkProperties testLinkProperties = new LinkProperties();
5988 testLinkProperties.setHttpProxy(testProxyInfo);
5989 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
5990 waitForIdle();
5991
5992 // Connect to VPN with proxy
5993 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5994 vpnNetworkAgent.connect(true);
5995 mMockVpn.connect();
5996 waitForIdle();
5997
5998 // Test that the VPN network returns a proxy, and the WiFi does not.
5999 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6000 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6001 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6002
6003 // Test that the VPN network returns no proxy when it is set to null.
6004 testLinkProperties.setHttpProxy(null);
6005 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6006 waitForIdle();
6007 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6008 assertNull(mService.getProxyForNetwork(null));
6009
6010 // Set WiFi proxy and check that the vpn proxy is still null.
6011 testLinkProperties.setHttpProxy(testProxyInfo);
6012 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6013 waitForIdle();
6014 assertNull(mService.getProxyForNetwork(null));
6015
6016 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6017 // correct proxy setting.
6018 vpnNetworkAgent.disconnect();
6019 waitForIdle();
6020 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6021 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6022 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6023 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006024
6025 @Test
6026 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6027 LinkProperties lp = new LinkProperties();
6028 lp.setInterfaceName("tun0");
6029 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6030 // The uid range needs to cover the test app so the network is visible to it.
6031 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006032 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006033
6034 // Connected VPN should have interface rules set up. There are two expected invocations,
6035 // one during VPN uid update, one during VPN LinkProperties update
6036 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6037 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6038 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6039 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6040 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6041
6042 vpnNetworkAgent.disconnect();
6043 waitForIdle();
6044
6045 // Disconnected VPN should have interface rules removed
6046 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6047 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6048 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6049 }
6050
6051 @Test
6052 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6053 LinkProperties lp = new LinkProperties();
6054 lp.setInterfaceName("tun0");
6055 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6056 // The uid range needs to cover the test app so the network is visible to it.
6057 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006058 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6059 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006060
6061 // Legacy VPN should not have interface rules set up
6062 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6063 }
6064
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09006065 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006066 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6067 throws Exception {
6068 LinkProperties lp = new LinkProperties();
6069 lp.setInterfaceName("tun0");
6070 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6071 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6072 // The uid range needs to cover the test app so the network is visible to it.
6073 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006074 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6075 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006076
6077 // IPv6 unreachable route should not be misinterpreted as a default route
6078 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6079 }
6080
6081 @Test
6082 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6083 LinkProperties lp = new LinkProperties();
6084 lp.setInterfaceName("tun0");
6085 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6086 // The uid range needs to cover the test app so the network is visible to it.
6087 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006088 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006089
6090 // Connected VPN should have interface rules set up. There are two expected invocations,
6091 // one during VPN uid update, one during VPN LinkProperties update
6092 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6093 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6094 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6095 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6096
6097 reset(mMockNetd);
6098 InOrder inOrder = inOrder(mMockNetd);
6099 lp.setInterfaceName("tun1");
6100 vpnNetworkAgent.sendLinkProperties(lp);
6101 waitForIdle();
6102 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6103 // removed first, then new rules added)
6104 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6105 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6106 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6107 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6108
6109 reset(mMockNetd);
6110 lp = new LinkProperties();
6111 lp.setInterfaceName("tun1");
6112 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6113 vpnNetworkAgent.sendLinkProperties(lp);
6114 waitForIdle();
6115 // VPN not routing everything should no longer have interface filtering rules
6116 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6117 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6118
6119 reset(mMockNetd);
6120 lp = new LinkProperties();
6121 lp.setInterfaceName("tun1");
6122 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6123 vpnNetworkAgent.sendLinkProperties(lp);
6124 waitForIdle();
6125 // Back to routing all IPv6 traffic should have filtering rules
6126 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6127 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6128 }
6129
6130 @Test
6131 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6132 LinkProperties lp = new LinkProperties();
6133 lp.setInterfaceName("tun0");
6134 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6135 // The uid range needs to cover the test app so the network is visible to it.
6136 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006137 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006138 Collections.singleton(vpnRange));
6139
6140 reset(mMockNetd);
6141 InOrder inOrder = inOrder(mMockNetd);
6142
6143 // Update to new range which is old range minus APP1, i.e. only APP2
6144 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6145 new UidRange(vpnRange.start, APP1_UID - 1),
6146 new UidRange(APP1_UID + 1, vpnRange.stop)));
6147 vpnNetworkAgent.setUids(newRanges);
6148 waitForIdle();
6149
6150 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6151 // Verify old rules are removed before new rules are added
6152 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6153 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6154 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6155 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6156 }
6157
Valentin Iftimec86ebba2019-09-24 13:32:13 +02006158 @Test
6159 public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
6160 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6161
6162 LinkProperties wifiLp = new LinkProperties();
6163 wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
6164 wifiLp.setWakeOnLanSupported(false);
6165
6166 // Default network switch should update ifaces.
6167 mWiFiNetworkAgent.connect(false);
6168 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6169 waitForIdle();
6170
6171 // ConnectivityService should have changed the WakeOnLanSupported to true
6172 wifiLp.setWakeOnLanSupported(true);
6173 assertEquals(wifiLp, mService.getActiveLinkProperties());
6174 }
6175
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006176
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006177 private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
Chalard Jeane7b24752019-06-20 16:01:19 +09006178 Set<UidRange> vpnRange) throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006179 final TestNetworkAgentWrapper
6180 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006181 vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
6182 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6183 mMockVpn.connect();
6184 mMockVpn.setUids(vpnRange);
6185 vpnNetworkAgent.connect(true);
6186 waitForIdle();
6187 return vpnNetworkAgent;
6188 }
6189
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006190 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6191 final PackageInfo packageInfo = new PackageInfo();
paulhu86e23eb2019-11-05 18:05:05 +08006192 if (hasSystemPermission) {
6193 packageInfo.requestedPermissions = new String[] {
6194 CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
6195 packageInfo.requestedPermissionsFlags = new int[] {
6196 REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
6197 } else {
6198 packageInfo.requestedPermissions = new String[0];
6199 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006200 packageInfo.applicationInfo = new ApplicationInfo();
6201 packageInfo.applicationInfo.privateFlags = 0;
6202 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6203 UserHandle.getAppId(uid));
6204 return packageInfo;
6205 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006206}