blob: 8eac95e523432249a126a6ded75f26c31b431c45 [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;
Chalard Jean587758b2019-11-29 16:41:50 +090099import static org.mockito.ArgumentMatchers.startsWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900100import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +0900101import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600102import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900103import static org.mockito.Mockito.doAnswer;
104import static org.mockito.Mockito.doNothing;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900105import static org.mockito.Mockito.doReturn;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000106import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -0800107import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600108import static org.mockito.Mockito.never;
109import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900110import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900111import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +0900112import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600113import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -0700114import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900115import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700116
junyulai7c469172019-01-16 20:23:34 +0800117import android.annotation.NonNull;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900118import android.app.AlarmManager;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900119import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400120import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400121import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900122import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900123import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700124import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400125import android.content.Intent;
126import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000127import android.content.pm.ApplicationInfo;
128import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100129import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000130import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900131import android.content.res.Resources;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400132import android.net.ConnectivityManager;
133import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900134import android.net.ConnectivityManager.PacketKeepalive;
135import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900136import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900137import android.net.ConnectivityThread;
Luke Huang65914772019-03-16 00:31:46 +0800138import android.net.IDnsResolver;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900139import android.net.IIpConnectivityMetrics;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800140import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900141import android.net.INetworkMonitor;
142import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800143import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700144import android.net.INetworkPolicyManager;
145import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800146import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900147import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800148import android.net.IpSecManager;
149import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900150import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700151import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700152import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400153import android.net.Network;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400154import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700155import android.net.NetworkFactory;
Chalard Jean9ca13772019-11-15 12:08:36 +0900156import android.net.NetworkInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400157import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700158import android.net.NetworkSpecifier;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900159import android.net.NetworkStack;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900160import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800161import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100162import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000163import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800164import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700165import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800166import android.net.SocketKeepalive;
markchien0df2ebc42019-09-30 14:40:57 +0800167import android.net.TetheringManager;
Chalard Jean0b214af2018-01-12 17:22:49 +0900168import android.net.UidRange;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900169import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900170import android.net.shared.NetworkMonitorUtils;
171import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900172import android.net.util.MultinetworkPolicyTracker;
Chalard Jean751bb3f2019-06-19 23:29:58 +0900173import android.os.BadParcelableException;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100174import android.os.Binder;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900175import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400176import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700177import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700178import android.os.HandlerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700179import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900180import android.os.Looper;
Etan Cohena7434272017-04-03 12:17:51 -0700181import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800182import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700183import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000184import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800185import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900186import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900187import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000188import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900189import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800190import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900191import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800192import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100193import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700194import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800195import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700196
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800197import androidx.test.InstrumentationRegistry;
Guang Zhub90866d2019-09-01 21:37:04 -0700198import androidx.test.filters.FlakyTest;
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800199import androidx.test.filters.SmallTest;
200import androidx.test.runner.AndroidJUnit4;
201
Chalard Jean587758b2019-11-29 16:41:50 +0900202import com.android.internal.app.IBatteryStats;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900203import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800204import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900205import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900206import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900207import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900208import com.android.internal.util.test.FakeSettingsProvider;
Chalard Jeandda156a2018-01-10 21:19:32 +0900209import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900210import com.android.server.connectivity.DefaultNetworkMetrics;
211import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900212import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800213import com.android.server.connectivity.Nat464Xlat;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900214import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000215import com.android.server.connectivity.ProxyTracker;
Chalard Jeandda156a2018-01-10 21:19:32 +0900216import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900217import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900218import com.android.server.net.NetworkPolicyManagerInternal;
Chalard Jeane7b24752019-06-20 16:01:19 +0900219import com.android.testutils.ExceptionUtils;
Chalard Jeance75e0e2019-05-28 16:48:32 +0900220import com.android.testutils.HandlerUtilsKt;
Chalard Jean059c4262019-09-30 17:51:12 +0900221import com.android.testutils.RecorderCallback.CallbackEntry;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900222import com.android.testutils.TestableNetworkCallback;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400223
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900224import org.junit.After;
225import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900226import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900227import org.junit.Test;
228import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900229import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000230import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900231import org.mockito.Mock;
232import org.mockito.MockitoAnnotations;
233import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900234import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900235
junyulai0c666972019-03-04 22:45:36 +0800236import java.io.IOException;
237import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800238import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000239import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700240import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900241import java.net.InetSocketAddress;
242import java.net.Socket;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400243import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900244import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100245import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800246import java.util.Collections;
dalyk1fcb7392018-03-05 12:42:22 -0500247import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100248import java.util.List;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100249import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900250import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800251import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800252import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800253import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900254import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900255import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700256import java.util.concurrent.atomic.AtomicBoolean;
Chalard Jean9ca13772019-11-15 12:08:36 +0900257import java.util.function.Predicate;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900258
259import kotlin.reflect.KClass;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700260
261/**
262 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400263 *
264 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900265 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700266 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900267@RunWith(AndroidJUnit4.class)
268@SmallTest
269public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700270 private static final String TAG = "ConnectivityServiceTest";
271
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900272 private static final int TIMEOUT_MS = 500;
Chalard Jeanb299b842019-09-27 17:13:14 +0900273 private static final int TEST_LINGER_DELAY_MS = 300;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900274 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
275 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
276 // timeout. For this, our assertions should run fast enough to leave less than
277 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
278 // supposedly fired, and the time we call expectCallback.
Chalard Jeanb299b842019-09-27 17:13:14 +0900279 private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900280 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
281 // complete before callbacks are verified.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900282 private static final int TEST_REQUEST_TIMEOUT_MS = 150;
283
284 private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900285
junyulai4a192e22018-06-13 15:00:37 +0800286 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700287 private static final String MOBILE_IFNAME = "test_rmnet_data0";
288 private static final String WIFI_IFNAME = "test_wlan0";
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200289 private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
Luke Huang65914772019-03-16 00:31:46 +0800290 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700291
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900292 private MockContext mServiceContext;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900293 private HandlerThread mCsHandlerThread;
294 private ConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900295 private WrappedConnectivityManager mCm;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900296 private TestNetworkAgentWrapper mWiFiNetworkAgent;
297 private TestNetworkAgentWrapper mCellNetworkAgent;
298 private TestNetworkAgentWrapper mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900299 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900300 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800301 private INetworkPolicyListener mPolicyListener;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900302 private WrappedMultinetworkPolicyTracker mPolicyTracker;
303 private HandlerThread mAlarmManagerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700304
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900305 @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
Hugo Benichi64901e52017-10-19 14:42:40 +0900306 @Mock IpConnectivityMetrics.Logger mMetricsService;
307 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900308 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600309 @Mock INetworkStatsService mStatsService;
Chalard Jean587758b2019-11-29 16:41:50 +0900310 @Mock IBatteryStats mBatteryStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800311 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800312 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800313 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900314 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100315 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000316 @Mock UserManager mUserManager;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900317 @Mock NotificationManager mNotificationManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900318 @Mock AlarmManager mAlarmManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900319
waynema13516842019-03-12 18:13:49 +0800320 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
321 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900322
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900323 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
324 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
325 // reflect the state of our test ConnectivityService.
326 private class WrappedConnectivityManager extends ConnectivityManager {
327 private Network mFakeBoundNetwork;
328
329 public synchronized boolean bindProcessToNetwork(Network network) {
330 mFakeBoundNetwork = network;
331 return true;
332 }
333
334 public synchronized Network getBoundNetworkForProcess() {
335 return mFakeBoundNetwork;
336 }
337
338 public WrappedConnectivityManager(Context context, ConnectivityService service) {
339 super(context, service);
340 }
341 }
342
Paul Jensend7b6ca92015-05-13 14:05:12 -0400343 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900344 private final MockContentResolver mContentResolver;
Chalard Jean9ca13772019-11-15 12:08:36 +0900345 // Contains all registered receivers since this object was created. Useful to clear
346 // them when needed, as BroadcastInterceptingContext does not provide this facility.
347 private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>();
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900348
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900349 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900350 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900351
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900352 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400353 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900354
355 mResources = spy(base.getResources());
356 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
357 thenReturn(new String[] {
358 "wifi,1,1,1,-1,true",
359 "mobile,0,0,0,-1,true",
360 "mobile_mms,2,0,2,60000,true",
Chalard Jean9ca13772019-11-15 12:08:36 +0900361 "mobile_supl,3,0,2,60000,true",
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900362 });
363
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200364 when(mResources.getStringArray(
365 com.android.internal.R.array.config_wakeonlan_supported_interfaces))
366 .thenReturn(new String[]{
367 WIFI_WOL_IFNAME,
368 });
369
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900370 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900371 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400372 }
373
374 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900375 public void startActivityAsUser(Intent intent, UserHandle handle) {
376 mStartedActivities.offer(intent);
377 }
378
Chalard Jeanf30d1e12019-06-27 08:24:51 +0000379 public Intent expectStartActivityIntent(int timeoutMs) {
380 Intent intent = null;
381 try {
382 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
383 } catch (InterruptedException e) {}
384 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
385 return intent;
386 }
387
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900388 public void expectNoStartActivityIntent(int timeoutMs) {
389 try {
390 assertNull("Received unexpected Intent to start activity",
391 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
392 } catch (InterruptedException e) {}
393 }
394
395 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900396 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900397 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900398 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900399 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000400 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900401 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400402 return super.getSystemService(name);
403 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900404
405 @Override
406 public ContentResolver getContentResolver() {
407 return mContentResolver;
408 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900409
410 @Override
411 public Resources getResources() {
412 return mResources;
413 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100414
415 @Override
416 public PackageManager getPackageManager() {
417 return mPackageManager;
418 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900419
420 @Override
421 public void enforceCallingOrSelfPermission(String permission, String message) {
422 // The mainline permission can only be held if signed with the network stack certificate
423 // Skip testing for this permission.
424 if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
425 // All other permissions should be held by the test or unnecessary: check as normal to
426 // make sure the code does not rely on unexpected permissions.
427 super.enforceCallingOrSelfPermission(permission, message);
428 }
Chalard Jean9ca13772019-11-15 12:08:36 +0900429
430 @Override
431 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
432 mRegisteredReceivers.add(receiver);
433 return super.registerReceiver(receiver, filter);
434 }
435
436 public void clearRegisteredReceivers() {
437 // super.unregisterReceiver is a no-op for receivers that are not registered (because
438 // they haven't been registered or because they have already been unregistered).
439 // For the same reason, don't bother clearing mRegisteredReceivers.
440 for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv);
441 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900442 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400443
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900444 private void waitForIdle() {
445 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
446 waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
447 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
448 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
449 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
450 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Hugo Benichibb91c572017-05-22 10:44:02 +0900451 }
452
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900453 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900454 if (agent == null) {
455 return;
456 }
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900457 agent.waitForIdle(timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900458 }
459
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900460 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +0900461 public void testWaitForIdle() throws Exception {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900462 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
463
464 // Tests that waitForIdle returns immediately if the service is already idle.
465 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900466 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900467 }
468
469 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900470 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900471 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900472 mWiFiNetworkAgent.connect(false);
473 waitFor(cv);
474 Network n = mWiFiNetworkAgent.getNetwork();
475 assertNotNull(n);
476
477 // Tests that calling waitForIdle waits for messages to be processed.
478 for (int i = 0; i < attempts; i++) {
479 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900480 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900481 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
482 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900483 }
484
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900485 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
486 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800487 @Ignore
Chalard Jeane7b24752019-06-20 16:01:19 +0900488 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900489 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900490 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900491 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Hugo Benichi5d540d12016-10-17 15:54:51 +0900492 mWiFiNetworkAgent.connect(false);
493 waitFor(cv);
494 Network n = mWiFiNetworkAgent.getNetwork();
495 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900496
497 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900498 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900499 for (int i = 0; i < attempts; i++) {
500 mWiFiNetworkAgent.setSignalStrength(i);
501 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
502 // We hit a race condition, as expected. Pass the test.
503 return;
504 }
505 }
506
507 // No race? There is a bug in this test.
508 fail("expected race condition at least once in " + attempts + " attempts");
509 }
510
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900511 private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800512 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
513 | NETWORK_VALIDATION_PROBE_HTTP
514 | NETWORK_VALIDATION_PROBE_HTTPS;
515 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
516 | NETWORK_VALIDATION_RESULT_VALID;
517 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
518 | NETWORK_VALIDATION_PROBE_FALLBACK
519 | NETWORK_VALIDATION_RESULT_PARTIAL;
520 private static final int VALIDATION_RESULT_INVALID = 0;
521
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900522 private INetworkMonitor mNetworkMonitor;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900523 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800524 private int mNmValidationResult = VALIDATION_RESULT_BASE;
lucaslin783f2212019-10-22 18:27:33 +0800525 private int mProbesCompleted;
526 private int mProbesSucceeded;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900527 private String mNmValidationRedirectUrl = null;
528 private boolean mNmProvNotificationRequested = false;
529
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900530 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
531 // Contains the redirectUrl from networkStatus(). Before reading, wait for
532 // mNetworkStatusReceived.
533 private String mRedirectUrl;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900534
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900535 TestNetworkAgentWrapper(int transport) throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100536 this(transport, new LinkProperties());
537 }
538
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900539 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
540 throws Exception {
541 super(transport, linkProperties, mServiceContext);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900542
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900543 // Waits for the NetworkAgent to be registered, which includes the creation of the
544 // NetworkMonitor.
545 waitForIdle(TIMEOUT_MS);
Chalard Jean3da8e0f2019-09-20 17:19:31 +0900546 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
547 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900548 }
549
550 @Override
551 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
552 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900553 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900554
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900555 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900556 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900557 return null;
558 };
559
Chalard Jeane7b24752019-06-20 16:01:19 +0900560 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
561 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900562
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900563 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900564 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
565 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
566 doNothing().when(mNetworkStack).makeNetworkMonitor(
567 nmNetworkCaptor.capture(),
568 any() /* name */,
569 nmCbCaptor.capture());
570
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900571 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400572 @Override
573 public void networkStatus(int status, String redirectUrl) {
574 mRedirectUrl = redirectUrl;
575 mNetworkStatusReceived.open();
576 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400577 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900578
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900579 assertEquals(na.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900580 mNmCallbacks = nmCbCaptor.getValue();
581
Chalard Jeane7b24752019-06-20 16:01:19 +0900582 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900583
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900584 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900585 }
586
Chalard Jeane7b24752019-06-20 16:01:19 +0900587 private void onValidationRequested() throws Exception {
588 if (mNmProvNotificationRequested
589 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
590 mNmCallbacks.hideProvisioningNotification();
591 mNmProvNotificationRequested = false;
592 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900593
lucaslin783f2212019-10-22 18:27:33 +0800594 mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
Chalard Jeane7b24752019-06-20 16:01:19 +0900595 mNmCallbacks.notifyNetworkTested(
596 mNmValidationResult, mNmValidationRedirectUrl);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900597
Chalard Jeane7b24752019-06-20 16:01:19 +0900598 if (mNmValidationRedirectUrl != null) {
599 mNmCallbacks.showProvisioningNotification(
600 "test_provisioning_notif_action", "com.android.test.package");
601 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900602 }
Paul Jensen3d911462015-06-12 06:40:24 -0400603 }
604
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900605 /**
606 * Connect without adding any internet capability.
607 */
Paul Jensene0988542015-06-25 15:30:08 -0400608 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900609 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400610 }
611
Paul Jensend7b6ca92015-05-13 14:05:12 -0400612 /**
Paul Jensene0988542015-06-25 15:30:08 -0400613 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400614 * @param validated Indicate if network should pretend to be validated.
615 */
616 public void connect(boolean validated) {
lucaslin783f2212019-10-22 18:27:33 +0800617 connect(validated, true, false /* isStrictMode */);
Hugo Benichi16f0a942017-06-20 14:07:59 +0900618 }
619
620 /**
621 * Transition this NetworkAgent to CONNECTED state.
622 * @param validated Indicate if network should pretend to be validated.
623 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
624 */
lucaslin783f2212019-10-22 18:27:33 +0800625 public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900626 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400627
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900628 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400629 final ConditionVariable validatedCv = new ConditionVariable();
630 if (validated) {
lucaslin783f2212019-10-22 18:27:33 +0800631 setNetworkValid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400632 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900633 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900634 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400635 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900636 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400637 public void onCapabilitiesChanged(Network network,
638 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400639 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900640 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400641 validatedCv.open();
642 }
643 }
644 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400645 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400646 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900647 if (hasInternet) {
648 addCapability(NET_CAPABILITY_INTERNET);
649 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400650
Paul Jensene0988542015-06-25 15:30:08 -0400651 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400652
653 if (validated) {
654 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400655 waitFor(validatedCv);
lucaslin783f2212019-10-22 18:27:33 +0800656 setNetworkInvalid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400657 }
658
659 if (callback != null) mCm.unregisterNetworkCallback(callback);
660 }
661
lucaslin783f2212019-10-22 18:27:33 +0800662 public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
663 setNetworkPortal(redirectUrl, isStrictMode);
664 connect(false, true /* hasInternet */, isStrictMode);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400665 }
666
lucasline252a742019-03-12 13:08:03 +0800667 public void connectWithPartialConnectivity() {
668 setNetworkPartial();
669 connect(false);
670 }
671
lucaslin783f2212019-10-22 18:27:33 +0800672 public void connectWithPartialValidConnectivity(boolean isStrictMode) {
673 setNetworkPartialValid(isStrictMode);
674 connect(false, true /* hasInternet */, isStrictMode);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900675 }
676
lucaslin783f2212019-10-22 18:27:33 +0800677 void setNetworkValid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900678 mNmValidationResult = VALIDATION_RESULT_VALID;
679 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800680 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP;
681 if (isStrictMode) {
682 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
683 }
684 // The probesCompleted equals to probesSucceeded for the case of valid network, so put
685 // the same value into two different parameter of the method.
686 setProbesStatus(probesSucceeded, probesSucceeded);
Erik Kline1d3db322017-02-28 16:20:20 +0900687 }
688
lucaslin783f2212019-10-22 18:27:33 +0800689 void setNetworkInvalid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900690 mNmValidationResult = VALIDATION_RESULT_INVALID;
691 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800692 int probesCompleted = VALIDATION_RESULT_BASE;
693 int probesSucceeded = VALIDATION_RESULT_INVALID;
694 // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
695 // tried to validate the private DNS but failed.
696 if (isStrictMode) {
697 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
698 probesSucceeded = probesCompleted;
699 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
700 }
701 setProbesStatus(probesCompleted, probesSucceeded);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900702 }
703
lucaslin783f2212019-10-22 18:27:33 +0800704 void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
705 setNetworkInvalid(isStrictMode);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900706 mNmValidationRedirectUrl = redirectUrl;
lucaslin783f2212019-10-22 18:27:33 +0800707 // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
708 // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
709 int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
710 int probesSucceeded = VALIDATION_RESULT_INVALID;
711 if (isStrictMode) {
712 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
713 }
714 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400715 }
716
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900717 void setNetworkPartial() {
718 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
719 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800720 int probesCompleted = VALIDATION_RESULT_BASE;
721 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
722 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400723 }
Paul Jensene0988542015-06-25 15:30:08 -0400724
lucaslin783f2212019-10-22 18:27:33 +0800725 void setNetworkPartialValid(boolean isStrictMode) {
726 setNetworkPartial();
727 mNmValidationResult |= VALIDATION_RESULT_VALID;
728 int probesCompleted = VALIDATION_RESULT_BASE;
729 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
730 // Suppose the partial network cannot pass the private DNS validation as well, so only
731 // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
732 if (isStrictMode) {
733 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
734 }
735 setProbesStatus(probesCompleted, probesSucceeded);
736 }
737
738 void setProbesStatus(int probesCompleted, int probesSucceeded) {
739 mProbesCompleted = probesCompleted;
740 mProbesSucceeded = probesSucceeded;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900741 }
Paul Jensen232437312016-04-06 09:51:26 -0400742
743 public String waitForRedirectUrl() {
744 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
745 return mRedirectUrl;
746 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900747
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900748 public void expectDisconnected() {
749 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900750 }
751
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900752 public void expectPreventReconnectReceived() {
753 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900754 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400755 }
756
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900757 /**
758 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
759 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900760 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900761 * expectRemoveRequests.
762 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700763 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400764 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
765 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400766 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700767
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900768 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900769 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
770 // once, then cause some other thread to add or remove requests, then call
771 // waitForRequests().
772 // It is not possible to wait for both add and remove requests. When adding, the queue
773 // contains the expected score. When removing, the value is unused, all matters is the
774 // number of objects in the queue.
775 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900776
777 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900778 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900779 private boolean mExpectingAdditions;
780
Etan Cohenddb720a2019-01-08 12:09:18 -0800781 // Used to collect the networks requests managed by this factory. This is a duplicate of
782 // the internal information stored in the NetworkFactory (which is private).
783 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
784
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700785 public MockNetworkFactory(Looper looper, Context context, String logTag,
786 NetworkCapabilities filter) {
787 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900788 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700789 }
790
791 public int getMyRequestCount() {
792 return getRequestCount();
793 }
794
795 protected void startNetwork() {
796 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400797 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700798 }
799
800 protected void stopNetwork() {
801 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400802 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700803 }
804
805 public boolean getMyStartRequested() {
806 return mNetworkStarted.get();
807 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400808
809 public ConditionVariable getNetworkStartedCV() {
810 mNetworkStartedCV.close();
811 return mNetworkStartedCV;
812 }
813
814 public ConditionVariable getNetworkStoppedCV() {
815 mNetworkStoppedCV.close();
816 return mNetworkStoppedCV;
817 }
818
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900819 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900820 protected void handleAddRequest(NetworkRequest request, int score,
821 int factorySerialNumber) {
822 synchronized (mExpectations) {
823 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900824
Chalard Jean05ab6812018-05-02 21:14:54 +0900825 assertNotNull("Added more requests than expected (" + request + " score : "
826 + score + ")", expectedScore);
827 // If we're expecting anything, we must be expecting additions.
828 if (!mExpectingAdditions) {
829 fail("Can't add requests while expecting requests to be removed");
830 }
831 if (expectedScore != score) {
832 fail("Expected score was " + expectedScore + " but actual was " + score
833 + " in added request");
834 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900835
Chalard Jean05ab6812018-05-02 21:14:54 +0900836 // Add the request.
837 mNetworkRequests.put(request.requestId, request);
838 super.handleAddRequest(request, score, factorySerialNumber);
839 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900840 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400841 }
842
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900843 @Override
844 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900845 synchronized (mExpectations) {
846 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900847
Chalard Jean05ab6812018-05-02 21:14:54 +0900848 assertTrue("Removed more requests than expected", expectedScore != null);
849 // If we're expecting anything, we must be expecting removals.
850 if (mExpectingAdditions) {
851 fail("Can't remove requests while expecting requests to be added");
852 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900853
Chalard Jean05ab6812018-05-02 21:14:54 +0900854 // Remove the request.
855 mNetworkRequests.remove(request.requestId);
856 super.handleRemoveRequest(request);
857 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900858 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400859 }
860
Etan Cohenddb720a2019-01-08 12:09:18 -0800861 // Trigger releasing the request as unfulfillable
862 public void triggerUnfulfillable(NetworkRequest r) {
863 super.releaseRequestAsUnfulfillableByAnyFactory(r);
864 }
865
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900866 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900867 if (mExpectations.size() != 0) {
868 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900869 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400870 }
871
Chalard Jean05ab6812018-05-02 21:14:54 +0900872 // Expects that requests with the specified scores will be added.
873 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900874 assertNoExpectations();
875 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900876 for (int score : scores) {
877 mExpectations.add(score);
878 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400879 }
880
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900881 // Expects that count requests will be removed.
882 public void expectRemoveRequests(final int count) {
883 assertNoExpectations();
884 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900885 for (int i = 0; i < count; ++i) {
886 mExpectations.add(0); // For removals the score is ignored so any value will do.
887 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900888 }
889
890 // Waits for the expected request additions or removals to happen within a timeout.
891 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900892 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
893 synchronized (mExpectations) {
894 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
895 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
896 }
897 }
898 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900899 final String msg = count + " requests still not " +
900 (mExpectingAdditions ? "added" : "removed") +
901 " after " + TIMEOUT_MS + " ms";
902 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900903 }
904
Etan Cohenddb720a2019-01-08 12:09:18 -0800905 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
906 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900907 waitForRequests();
908 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800909 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400910 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700911 }
912
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900913 private static Looper startHandlerThreadAndReturnLooper() {
914 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
915 handlerThread.start();
916 return handlerThread.getLooper();
917 }
918
919 private class MockVpn extends Vpn {
920 // TODO : the interactions between this mock and the mock network agent are too
921 // hard to get right at this moment, because it's unclear in which case which
922 // target needs to get a method call or both, and in what order. It's because
923 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
924 // parent class of MockVpn agent wants that responsibility.
925 // That being said inside the test it should be possible to make the interactions
926 // harder to get wrong with precise speccing, judicious comments, helper methods
927 // and a few sprinkled assertions.
928
929 private boolean mConnected = false;
930 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
931 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900932 private TestNetworkAgentWrapper mMockNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900933
934 public MockVpn(int userId) {
935 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
936 userId);
937 }
938
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900939 public void setNetworkAgent(TestNetworkAgentWrapper agent) {
940 agent.waitForIdle(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900941 mMockNetworkAgent = agent;
942 mNetworkAgent = agent.getNetworkAgent();
943 mNetworkCapabilities.set(agent.getNetworkCapabilities());
944 }
945
946 public void setUids(Set<UidRange> uids) {
947 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800948 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900949 }
950
951 @Override
952 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800953 if (mMockNetworkAgent == null) {
954 return NETID_UNSET;
955 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900956 return mMockNetworkAgent.getNetwork().netId;
957 }
958
959 @Override
960 public boolean appliesToUid(int uid) {
961 return mConnected; // Trickery to simplify testing.
962 }
963
964 @Override
965 protected boolean isCallerEstablishedOwnerLocked() {
966 return mConnected; // Similar trickery
967 }
968
Varun Anandc51b06d2019-02-25 17:22:02 -0800969 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900970 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
971 mConnected = true;
972 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -0800973 mConfig.isMetered = isAlwaysMetered;
974 }
975
976 public void connectAsAlwaysMetered() {
977 connect(true /* isAlwaysMetered */);
978 }
979
980 public void connect() {
981 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900982 }
983
984 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -0800985 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
986 if (!mConnected) return null;
987 super.updateCapabilities(defaultNetwork);
988 // Because super.updateCapabilities will update the capabilities of the agent but
989 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900990 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -0800991 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900992 }
993
994 private void copyCapabilitiesToNetworkAgent() {
995 if (null != mMockNetworkAgent) {
996 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
997 false /* sendToConnectivityService */);
998 }
999 }
1000
1001 public void disconnect() {
1002 mConnected = false;
1003 mConfig = null;
1004 }
1005 }
1006
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001007 private void mockVpn(int uid) {
1008 synchronized (mService.mVpns) {
1009 int userId = UserHandle.getUserId(uid);
1010 mMockVpn = new MockVpn(userId);
1011 // This has no effect unless the VPN is actually connected, because things like
1012 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1013 // netId, and check if that network is actually connected.
1014 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001015 }
1016 }
1017
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001018 private void setUidRulesChanged(int uidRules) throws RemoteException {
1019 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1020 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001021
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001022 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
1023 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1024 }
1025
1026 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1027 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1028 }
1029
1030 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1031 volatile boolean mConfigRestrictsAvoidBadWifi;
1032 volatile int mConfigMeteredMultipathPreference;
1033
1034 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001035 super(c, h, r);
1036 }
1037
1038 @Override
1039 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001040 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +09001041 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001042
1043 @Override
1044 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001045 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +08001046 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001047 }
1048
Paul Jensen3d911462015-06-12 06:40:24 -04001049 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001050 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1051 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001052 */
1053 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001054 if (conditionVariable.block(TIMEOUT_MS)) {
1055 return;
1056 }
1057 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001058 }
1059
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001060 private static final int VPN_USER = 0;
1061 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1062 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1063 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1064
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001065 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001066 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001067 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001068
Hugo Benichi64901e52017-10-19 14:42:40 +09001069 MockitoAnnotations.initMocks(this);
1070 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1071
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001072 when(mUserManager.getUsers(eq(true))).thenReturn(
1073 Arrays.asList(new UserInfo[] {
1074 new UserInfo(VPN_USER, "", 0),
1075 }));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001076
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001077 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1078 // http://b/25897652 .
1079 if (Looper.myLooper() == null) {
1080 Looper.prepare();
1081 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001082 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001083
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001084 FakeSettingsProvider.clearSettingsProvider();
1085 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1086 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001087 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1088 LocalServices.addService(
1089 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001090
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001091 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1092 mAlarmManagerThread.start();
1093 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1094
1095 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1096 final ConnectivityService.Dependencies deps = makeDependencies();
1097 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001098 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001099 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001100 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001101 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001102 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001103 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001104 deps);
1105 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1106 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001107
Mike Yuf9729752018-08-17 15:22:05 +08001108 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1109 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1110 verify(mNpm).registerListener(policyListenerCaptor.capture());
1111 mPolicyListener = policyListenerCaptor.getValue();
1112
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001113 // Create local CM before sending system ready so that we can answer
1114 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001115 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001116 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001117 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001118 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001119
1120 // Ensure that the default setting for Captive Portals is used for most tests
1121 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001122 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001123 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001124 }
1125
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001126 private ConnectivityService.Dependencies makeDependencies() {
1127 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1128 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1129 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1130
1131 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1132 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1133 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
1134 doReturn(mNetworkStack).when(deps).getNetworkStack();
1135 doReturn(systemProperties).when(deps).getSystemProperties();
markchien0df2ebc42019-09-30 14:40:57 +08001136 doReturn(mock(TetheringManager.class)).when(deps).getTetheringManager();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001137 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1138 doReturn(mMetricsService).when(deps).getMetricsLogger();
1139 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1140 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
Chalard Jean587758b2019-11-29 16:41:50 +09001141 doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001142 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1143 doAnswer(inv -> {
1144 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1145 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1146 return mPolicyTracker;
1147 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1148
1149 return deps;
1150 }
1151
1152 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1153 doAnswer(inv -> {
1154 final long when = inv.getArgument(1);
1155 final WakeupMessage wakeupMsg = inv.getArgument(3);
1156 final Handler handler = inv.getArgument(4);
1157
1158 long delayMs = when - SystemClock.elapsedRealtime();
1159 if (delayMs < 0) delayMs = 0;
1160 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1161 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1162 + "ms into the future: " + delayMs);
1163 }
1164 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1165 delayMs);
1166
1167 return null;
1168 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1169 any(WakeupMessage.class), any());
1170
1171 doAnswer(inv -> {
1172 final WakeupMessage wakeupMsg = inv.getArgument(0);
1173 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1174 return null;
1175 }).when(am).cancel(any(WakeupMessage.class));
1176 }
1177
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001178 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001179 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001180 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001181 if (mCellNetworkAgent != null) {
1182 mCellNetworkAgent.disconnect();
1183 mCellNetworkAgent = null;
1184 }
1185 if (mWiFiNetworkAgent != null) {
1186 mWiFiNetworkAgent.disconnect();
1187 mWiFiNetworkAgent = null;
1188 }
1189 if (mEthernetNetworkAgent != null) {
1190 mEthernetNetworkAgent.disconnect();
1191 mEthernetNetworkAgent = null;
1192 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001193 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001194
1195 mCsHandlerThread.quitSafely();
1196 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001197 }
1198
Rubin Xu9e64dc02019-04-23 18:04:14 +01001199 private void mockDefaultPackages() throws Exception {
1200 final String testPackageName = mContext.getPackageName();
1201 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1202 testPackageName, PackageManager.GET_PERMISSIONS);
1203 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1204 new String[] {testPackageName});
1205 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1206 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1207
1208 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1209 Arrays.asList(new PackageInfo[] {
1210 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1211 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1212 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1213 }));
1214 }
1215
Paul Jensend7b6ca92015-05-13 14:05:12 -04001216 private void verifyActiveNetwork(int transport) {
1217 // Test getActiveNetworkInfo()
1218 assertNotNull(mCm.getActiveNetworkInfo());
1219 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1220 // Test getActiveNetwork()
1221 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001222 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001223 if (!NetworkCapabilities.isValidTransport(transport)) {
1224 throw new IllegalStateException("Unknown transport " + transport);
1225 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001226 switch (transport) {
1227 case TRANSPORT_WIFI:
1228 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1229 break;
1230 case TRANSPORT_CELLULAR:
1231 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1232 break;
1233 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001234 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001235 }
1236 // Test getNetworkInfo(Network)
1237 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001238 assertEquals(transportToLegacyType(transport),
1239 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001240 // Test getNetworkCapabilities(Network)
1241 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1242 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1243 }
1244
1245 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001246 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001247 // Test getActiveNetworkInfo()
1248 assertNull(mCm.getActiveNetworkInfo());
1249 // Test getActiveNetwork()
1250 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001251 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001252 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001253 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001254 }
1255
1256 /**
1257 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1258 * broadcasts are received.
1259 */
Chalard Jean407deb72019-11-19 16:14:30 +09001260 private ConditionVariable registerConnectivityBroadcast(final int count) {
1261 return registerConnectivityBroadcastThat(count, intent -> true);
Chalard Jean9ca13772019-11-15 12:08:36 +09001262 }
1263
Chalard Jean407deb72019-11-19 16:14:30 +09001264 private ConditionVariable registerConnectivityBroadcastThat(final int count,
Chalard Jean9ca13772019-11-15 12:08:36 +09001265 @NonNull final Predicate<Intent> filter) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001266 final ConditionVariable cv = new ConditionVariable();
Chalard Jean9ca13772019-11-15 12:08:36 +09001267 final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
1268 intentFilter.addAction(CONNECTIVITY_ACTION_SUPL);
1269 final BroadcastReceiver receiver = new BroadcastReceiver() {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001270 private int remaining = count;
1271 public void onReceive(Context context, Intent intent) {
Chalard Jean9ca13772019-11-15 12:08:36 +09001272 if (!filter.test(intent)) return;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001273 if (--remaining == 0) {
1274 cv.open();
1275 mServiceContext.unregisterReceiver(this);
1276 }
1277 }
Chalard Jean9ca13772019-11-15 12:08:36 +09001278 };
1279 mServiceContext.registerReceiver(receiver, intentFilter);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001280 return cv;
1281 }
1282
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001283 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001284 public void testNetworkTypes() {
1285 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1286 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1287 // will fail. Failing here is much easier to debug.
1288 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1289 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001290 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1291 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1292
1293 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1294 // mocks, this assert exercises the ConnectivityService code path that ensures that
1295 // TYPE_ETHERNET is supported if the ethernet service is running.
1296 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001297 }
1298
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001299 @Test
Chalard Jean9ca13772019-11-15 12:08:36 +09001300 public void testNetworkFeature() throws Exception {
1301 // Connect the cell agent and wait for the connected broadcast.
1302 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1303 mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
Chalard Jean407deb72019-11-19 16:14:30 +09001304 final ConditionVariable cv1 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001305 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE);
1306 mCellNetworkAgent.connect(true);
1307 waitFor(cv1);
1308
1309 // Build legacy request for SUPL.
1310 final NetworkCapabilities legacyCaps = new NetworkCapabilities();
1311 legacyCaps.addTransportType(TRANSPORT_CELLULAR);
1312 legacyCaps.addCapability(NET_CAPABILITY_SUPL);
1313 final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
1314 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
1315
1316 // Send request and check that the legacy broadcast for SUPL is sent correctly.
1317 final TestNetworkCallback callback = new TestNetworkCallback();
Chalard Jean407deb72019-11-19 16:14:30 +09001318 final ConditionVariable cv2 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001319 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1320 mCm.requestNetwork(legacyRequest, callback);
1321 callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1322 waitFor(cv2);
1323
1324 // File another request, withdraw it and make sure no broadcast is sent
Chalard Jean407deb72019-11-19 16:14:30 +09001325 final ConditionVariable cv3 = registerConnectivityBroadcast(1);
Chalard Jean9ca13772019-11-15 12:08:36 +09001326 final TestNetworkCallback callback2 = new TestNetworkCallback();
1327 mCm.requestNetwork(legacyRequest, callback2);
1328 callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1329 mCm.unregisterNetworkCallback(callback2);
1330 assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent
1331 // As the broadcast did not fire, the receiver was not unregistered. Do this now.
1332 mServiceContext.clearRegisteredReceivers();
1333
1334 // Withdraw the request and check that the broadcast for disconnection is sent.
Chalard Jean407deb72019-11-19 16:14:30 +09001335 final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent ->
Chalard Jean9ca13772019-11-15 12:08:36 +09001336 !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected()
1337 && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1338 mCm.unregisterNetworkCallback(callback);
1339 waitFor(cv4);
1340
1341 // Re-file the request and expect the connected broadcast again
Chalard Jean407deb72019-11-19 16:14:30 +09001342 final ConditionVariable cv5 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001343 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1344 final TestNetworkCallback callback3 = new TestNetworkCallback();
1345 mCm.requestNetwork(legacyRequest, callback3);
1346 callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1347 waitFor(cv5);
1348
1349 // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one
1350 // for mobile. Use a small hack to check that both have been sent, but the order is
1351 // not contractual.
1352 final AtomicBoolean vanillaAction = new AtomicBoolean(false);
1353 final AtomicBoolean suplAction = new AtomicBoolean(false);
Chalard Jean407deb72019-11-19 16:14:30 +09001354 final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> {
Chalard Jean9ca13772019-11-15 12:08:36 +09001355 if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
1356 vanillaAction.set(true);
1357 } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) {
1358 suplAction.set(true);
1359 }
1360 return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
1361 });
1362 mCellNetworkAgent.disconnect();
1363 waitFor(cv6);
1364 assertTrue(vanillaAction.get());
1365 assertTrue(suplAction.get());
1366 }
1367
1368 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001369 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001370 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001371 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1372 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001373 assertNull(mCm.getActiveNetworkInfo());
1374 assertNull(mCm.getActiveNetwork());
1375 // Test bringing up validated cellular.
Chalard Jean407deb72019-11-19 16:14:30 +09001376 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001377 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001378 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001379 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001380 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001381 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1382 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1383 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1384 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1385 // Test bringing up validated WiFi.
Chalard Jean407deb72019-11-19 16:14:30 +09001386 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001387 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001388 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001389 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001390 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001391 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1392 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1393 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1394 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1395 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001396 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001397 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001398 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001399 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001400 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001401 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1402 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001403 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001404 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001405 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001406 verifyNoNetwork();
1407 }
1408
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001409 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001410 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1411 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001412 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001413 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001414 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001415 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001416 verifyActiveNetwork(TRANSPORT_WIFI);
1417 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001418 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001419 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001420 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001421 verifyActiveNetwork(TRANSPORT_WIFI);
1422 // Test cellular disconnect.
1423 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001424 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001425 verifyActiveNetwork(TRANSPORT_WIFI);
1426 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001427 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001428 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001429 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001430 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001431 verifyActiveNetwork(TRANSPORT_CELLULAR);
1432 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001433 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001434 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001435 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001436 verifyActiveNetwork(TRANSPORT_WIFI);
1437 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001438 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001439 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001440 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001441 verifyNoNetwork();
1442 }
1443
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001444 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001445 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1446 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001447 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001448 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001449 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001450 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001451 verifyActiveNetwork(TRANSPORT_CELLULAR);
1452 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001453 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001454 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001455 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001456 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001457 verifyActiveNetwork(TRANSPORT_WIFI);
1458 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001459 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001460 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001461 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001462 verifyActiveNetwork(TRANSPORT_CELLULAR);
1463 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001464 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001465 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001466 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001467 verifyNoNetwork();
1468 }
1469
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001470 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001471 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001472 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001473 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001474 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001475 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001476 waitFor(cv);
1477 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001478 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001479 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001480 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001481 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001482 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001483 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001484 waitFor(cv);
1485 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001486 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1487 NET_CAPABILITY_VALIDATED));
1488 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001489 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001490 mCellNetworkAgent.disconnect();
1491 waitFor(cv);
1492 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001493 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001494 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001495 NET_CAPABILITY_VALIDATED));
1496 }
1497
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001498 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001499 public void testCellularOutscoresWeakWifi() throws Exception {
1500 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001501 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001502 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001503 mCellNetworkAgent.connect(true);
1504 waitFor(cv);
1505 verifyActiveNetwork(TRANSPORT_CELLULAR);
1506 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001507 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001508 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001509 mWiFiNetworkAgent.connect(true);
1510 waitFor(cv);
1511 verifyActiveNetwork(TRANSPORT_WIFI);
1512 // Test WiFi getting really weak.
Chalard Jean407deb72019-11-19 16:14:30 +09001513 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001514 mWiFiNetworkAgent.adjustScore(-11);
1515 waitFor(cv);
1516 verifyActiveNetwork(TRANSPORT_CELLULAR);
1517 // Test WiFi restoring signal strength.
Chalard Jean407deb72019-11-19 16:14:30 +09001518 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001519 mWiFiNetworkAgent.adjustScore(11);
1520 waitFor(cv);
1521 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001522 }
1523
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001524 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001525 public void testReapingNetwork() throws Exception {
1526 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1527 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001528 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001529 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001530 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001531 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1532 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001533 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001534 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001535 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001536 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001537 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001538 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001539 mWiFiNetworkAgent.connect(true);
1540 waitFor(cv);
1541 verifyActiveNetwork(TRANSPORT_WIFI);
1542 // Test bringing up unvalidated cellular.
1543 // Expect it to be torn down because it could never be the highest scoring network
1544 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001545 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001546 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001547 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001548 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001549 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001550 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001551 }
1552
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001553 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001554 public void testCellularFallback() throws Exception {
1555 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001556 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001557 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001558 mCellNetworkAgent.connect(true);
1559 waitFor(cv);
1560 verifyActiveNetwork(TRANSPORT_CELLULAR);
1561 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001562 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001563 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001564 mWiFiNetworkAgent.connect(true);
1565 waitFor(cv);
1566 verifyActiveNetwork(TRANSPORT_WIFI);
1567 // Reevaluate WiFi (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001568 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001569 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1570 NET_CAPABILITY_VALIDATED));
1571 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1572 // Should quickly fall back to Cellular.
1573 waitFor(cv);
1574 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1575 NET_CAPABILITY_VALIDATED));
1576 verifyActiveNetwork(TRANSPORT_CELLULAR);
1577 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001578 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001579 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1580 NET_CAPABILITY_VALIDATED));
1581 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1582 // Should quickly fall back to WiFi.
1583 waitFor(cv);
1584 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1585 NET_CAPABILITY_VALIDATED));
1586 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1587 NET_CAPABILITY_VALIDATED));
1588 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001589 }
1590
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001591 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001592 public void testWiFiFallback() throws Exception {
1593 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001594 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001595 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001596 mWiFiNetworkAgent.connect(false);
1597 waitFor(cv);
1598 verifyActiveNetwork(TRANSPORT_WIFI);
1599 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001600 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001601 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001602 mCellNetworkAgent.connect(true);
1603 waitFor(cv);
1604 verifyActiveNetwork(TRANSPORT_CELLULAR);
1605 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001606 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001607 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1608 NET_CAPABILITY_VALIDATED));
1609 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1610 // Should quickly fall back to WiFi.
1611 waitFor(cv);
1612 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1613 NET_CAPABILITY_VALIDATED));
1614 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001615 }
1616
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001617 @Test
1618 public void testRequiresValidation() {
1619 assertTrue(NetworkMonitorUtils.isValidationRequired(
1620 mCm.getDefaultRequest().networkCapabilities));
1621 }
1622
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001623 /**
1624 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1625 * this class receives, by calling expectCallback() exactly once each time a callback is
1626 * received. assertNoCallback may be called at any time.
1627 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001628 private class TestNetworkCallback extends TestableNetworkCallback {
Chalard Jeanb299b842019-09-27 17:13:14 +09001629 TestNetworkCallback() {
1630 super(TEST_CALLBACK_TIMEOUT_MS);
1631 }
1632
Chalard Jean6f4216f2019-06-05 01:40:32 +09001633 @Override
1634 public void assertNoCallback() {
1635 // TODO: better support this use case in TestableNetworkCallback
1636 waitForIdle();
1637 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001638 }
Paul Jensen3d911462015-06-12 06:40:24 -04001639
Erik Klineacdd6392016-07-07 16:50:58 +09001640 @Override
Chalard Jean059c4262019-09-30 17:51:12 +09001641 public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
Chalard Jean6f4216f2019-06-05 01:40:32 +09001642 final long timeoutMs) {
1643 final T callback = super.expectCallback(type, n, timeoutMs);
Chalard Jean059c4262019-09-30 17:51:12 +09001644 if (callback instanceof CallbackEntry.Losing) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09001645 // TODO : move this to the specific test(s) needing this rather than here.
Chalard Jean059c4262019-09-30 17:51:12 +09001646 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001647 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001648 String msg = String.format(
1649 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001650 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001651 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001652 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001653 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001654 }
1655 }
1656
1657 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1658 // only be declared in a static or top level type".
1659 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1660 for (TestNetworkCallback c : callbacks) {
1661 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001662 }
1663 }
1664
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001665 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001666 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001667 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001668 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1669 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001670 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1671 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001672 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1673 .addTransportType(TRANSPORT_WIFI).build();
1674 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1675 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001676 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001677 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1678 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1679
1680 // Test unvalidated networks
Chalard Jean407deb72019-11-19 16:14:30 +09001681 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001682 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001683 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001684 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1685 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001686 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1687 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001688 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001689
Paul Jensen3d911462015-06-12 06:40:24 -04001690 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1691 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001692 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001693 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001694 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1695
Chalard Jean407deb72019-11-19 16:14:30 +09001696 cv = registerConnectivityBroadcast(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001697 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001698 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001699 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1700 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001701 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1702 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001703 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001704
Chalard Jean407deb72019-11-19 16:14:30 +09001705 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001706 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001707 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1708 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001709 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001710 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001711 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001712
Chalard Jean407deb72019-11-19 16:14:30 +09001713 cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001714 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001715 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1716 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001717 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001718 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001719
1720 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001721 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001722 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001723 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1724 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001725 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001726 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001727
Paul Jensen3d911462015-06-12 06:40:24 -04001728 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1729 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001730 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001731 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001732 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1733
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001734 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001735 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001736 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001737 genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001738 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001739 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001740 cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001741 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001742 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001743
Paul Jensen3d911462015-06-12 06:40:24 -04001744 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001745 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1746 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001747 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001748
Paul Jensen3d911462015-06-12 06:40:24 -04001749 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001750 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1751 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001752 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001753 }
1754
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001755 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001756 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001757 // This test would be flaky with the default 120ms timer: that is short enough that
1758 // lingered networks are torn down before assertions can be run. We don't want to mock the
1759 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1760 // in detecting races.
1761 mService.mLingerDelayMs = 300;
1762
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001763 NetworkRequest request = new NetworkRequest.Builder()
1764 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1765 .build();
1766 TestNetworkCallback callback = new TestNetworkCallback();
1767 mCm.registerNetworkCallback(request, callback);
1768
1769 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1770 mCm.registerDefaultNetworkCallback(defaultCallback);
1771
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001772 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1773 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1774 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001775
1776 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1777 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1778 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1779
1780 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001781 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1782 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001783 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001784 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001785
1786 mWiFiNetworkAgent.connect(true);
1787 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1788 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001789 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001790 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001791 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001792 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001793 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001794 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001795 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001796
1797 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001798 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001799 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001800 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001801 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001802 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001803 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001804 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001805
1806 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001807 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
1808 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001809 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001810 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001811
1812 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001813 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001814 if (i % 2 == 0) {
1815 mWiFiNetworkAgent.adjustScore(-15);
1816 oldNetwork = mWiFiNetworkAgent;
1817 newNetwork = mCellNetworkAgent;
1818 } else {
1819 mWiFiNetworkAgent.adjustScore(15);
1820 oldNetwork = mCellNetworkAgent;
1821 newNetwork = mWiFiNetworkAgent;
1822
1823 }
Chalard Jean059c4262019-09-30 17:51:12 +09001824 callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001825 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1826 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001827 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001828 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1829 }
1830 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1831
1832 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1833 // if the network is still up.
1834 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001835 // We expect a notification about the capabilities change, and nothing else.
1836 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1837 defaultCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09001838 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001839 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001840
1841 // Wifi no longer satisfies our listen, which is for an unmetered network.
1842 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001843 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1844
1845 // Disconnect our test networks.
1846 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001847 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001848 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001849 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001850 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001851 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001852 waitForIdle();
1853 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001854
1855 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09001856 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001857
1858 // Check that a network is only lingered or torn down if it would not satisfy a request even
1859 // if it validated.
1860 request = new NetworkRequest.Builder().clearCapabilities().build();
1861 callback = new TestNetworkCallback();
1862
1863 mCm.registerNetworkCallback(request, callback);
1864
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001865 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001866 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09001867 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1868 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001869 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001870 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001871
1872 // Bring up wifi with a score of 20.
1873 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001874 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001875 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09001876 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1877 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001878 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001879 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001880
1881 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001882 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1883 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001884 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001885 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001886 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001887
1888 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001889 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001890 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001891 mWiFiNetworkAgent.adjustScore(50);
1892 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09001893 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001894 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001895 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001896 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001897 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001898
1899 // Tear down wifi.
1900 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001901 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1902 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001903 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001904 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001905 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001906
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001907 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
1908 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001909 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001910 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001911 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001912 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001913 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001914 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001915 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001916 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001917 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001918
1919 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001920 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1921 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001922 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001923 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001924 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1925 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001926 waitForIdle();
1927 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001928
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001929 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001930 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001931 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001932 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1933 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001934 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001935 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001936 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001937 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
1938 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001939 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001940 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001941 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001942 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001943
1944 NetworkRequest cellRequest = new NetworkRequest.Builder()
1945 .addTransportType(TRANSPORT_CELLULAR).build();
1946 NetworkCallback noopCallback = new NetworkCallback();
1947 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001948 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
1949 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001950 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09001951 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001952
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001953 // Similar to the above: lingering can start even after the lingered request is removed.
1954 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001955 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001956 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1957 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001958 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001959 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001960
1961 // Cell is now the default network. Pin it with a cell-specific request.
1962 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
1963 mCm.requestNetwork(cellRequest, noopCallback);
1964
1965 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001966 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001967 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001968 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
1969 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001970 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001971 // The default request is lingering on cell, but nothing happens to cell, and we send no
1972 // callbacks for it, because it's kept up by cellRequest.
1973 callback.assertNoCallback();
1974 // Now unregister cellRequest and expect cell to start lingering.
1975 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09001976 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001977
1978 // Let linger run its course.
1979 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001980 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09001981 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001982
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001983 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
1984 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
1985 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001986 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001987 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001988 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001989 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001990 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001991 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001992 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
1993 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001994 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001995
1996 // Let linger run its course.
Chalard Jean059c4262019-09-30 17:51:12 +09001997 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09001998
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001999 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002000 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002001 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2002 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2003 trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002004
2005 mCm.unregisterNetworkCallback(callback);
2006 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002007 mCm.unregisterNetworkCallback(trackDefaultCallback);
2008 }
2009
paulhu86e23eb2019-11-05 18:05:05 +08002010 private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
2011 final String testPackageName = mContext.getPackageName();
2012 when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
2013 .thenReturn(buildPackageInfo(true, uid));
2014 mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
2015 }
2016
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002017 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002018 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002019 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08002020 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Chalard Jean1fa777d2018-02-16 16:07:53 +09002021 NetworkRequest request = new NetworkRequest.Builder()
2022 .clearCapabilities()
2023 .build();
2024 TestNetworkCallback callback = new TestNetworkCallback();
2025 mCm.registerNetworkCallback(request, callback);
2026
2027 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2028 mCm.registerDefaultNetworkCallback(defaultCallback);
2029
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002030 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2031 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002032
2033 mCellNetworkAgent.connect(true);
2034 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2035 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2036
2037 // Wifi comes up and cell lingers.
2038 mWiFiNetworkAgent.connect(true);
2039 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2040 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002041 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002042 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2043
2044 // File a request for cellular, then release it.
2045 NetworkRequest cellRequest = new NetworkRequest.Builder()
2046 .addTransportType(TRANSPORT_CELLULAR).build();
2047 NetworkCallback noopCallback = new NetworkCallback();
2048 mCm.requestNetwork(cellRequest, noopCallback);
2049 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002050 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002051
2052 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002053 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002054 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2055 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2056 lingerTimeoutMs);
2057
2058 // Clean up.
2059 mCm.unregisterNetworkCallback(defaultCallback);
2060 mCm.unregisterNetworkCallback(callback);
2061 }
2062
2063 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002064 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002065 NetworkRequest request = new NetworkRequest.Builder()
2066 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2067 .build();
2068 TestNetworkCallback callback = new TestNetworkCallback();
2069 mCm.registerNetworkCallback(request, callback);
2070
2071 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002072 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002073 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002074 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002075
2076 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002077 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002078 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002079 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002080 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002081
2082 // Cell Remains the default.
2083 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2084
2085 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2086 // it's explicitly selected.
2087 mWiFiNetworkAgent.adjustScore(-40);
2088 mWiFiNetworkAgent.adjustScore(40);
2089 callback.assertNoCallback();
2090
2091 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2092 // wifi even though it's unvalidated.
2093 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002094 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002095 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2096
2097 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2098 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002099 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002100 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002101 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002102 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002103 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002104
2105 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2106 // network to disconnect.
2107 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002108 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002109
2110 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002111 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002112 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002113 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002114 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002115 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002116 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2117 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2118
2119 // BUG: the network will no longer linger, even though it's validated and outscored.
2120 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002121 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002122 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002123 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002124 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2125 callback.assertNoCallback();
2126
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002127 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
2128 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
2129 // wifi immediately.
2130 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002131 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002132 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002133 mWiFiNetworkAgent.explicitlySelected(true, true);
2134 mWiFiNetworkAgent.connect(false);
2135 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002136 callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002137 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2138 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002139 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002140
2141 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
2142 // Check that the network is not scored specially and that the device prefers cell data.
2143 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002144 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002145 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002146 mWiFiNetworkAgent.explicitlySelected(false, true);
2147 mWiFiNetworkAgent.connect(false);
2148 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2149 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2150
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002151 // Clean up.
2152 mWiFiNetworkAgent.disconnect();
2153 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002154
Chalard Jean059c4262019-09-30 17:51:12 +09002155 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2156 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002157 }
2158
Chalard Jean05ab6812018-05-02 21:14:54 +09002159 private int[] makeIntArray(final int size, final int value) {
2160 final int[] array = new int[size];
2161 Arrays.fill(array, value);
2162 return array;
2163 }
2164
Paul Jensen85cf78e2015-06-25 13:25:07 -04002165 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002166 // Verify NOT_RESTRICTED is set appropriately
2167 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2168 .build().networkCapabilities;
2169 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2170 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2171 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002172 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002173 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2174 } else {
2175 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2176 }
2177
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002178 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002179 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002180 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2181 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002182 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002183 mServiceContext, "testFactory", filter);
2184 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002185 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002186 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002187 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002188 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002189 int expectedRequestCount = 1;
2190 NetworkCallback networkCallback = null;
2191 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2192 // add one.
2193 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002194 assertFalse(testFactory.getMyStartRequested());
2195 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2196 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002197 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002198 mCm.requestNetwork(request, networkCallback);
2199 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002200 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002201 }
Paul Jensen3d911462015-06-12 06:40:24 -04002202 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002203 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2204 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002205
Paul Jensen85cf78e2015-06-25 13:25:07 -04002206 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002207 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002208 // Rather than create a validated network which complicates things by registering it's
2209 // own NetworkRequest during startup, just bump up the score to cancel out the
2210 // unvalidated penalty.
2211 testAgent.adjustScore(40);
2212 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002213
2214 // When testAgent connects, ConnectivityService will re-send us all current requests with
2215 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2216 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002217 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002218 testAgent.connect(false);
2219 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002220 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002221 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002222 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002223
Paul Jensen85cf78e2015-06-25 13:25:07 -04002224 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002225 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002226 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002227 ConnectivityManager.NetworkCallback[] networkCallbacks =
2228 new ConnectivityManager.NetworkCallback[10];
2229 for (int i = 0; i< networkCallbacks.length; i++) {
2230 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2231 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002232 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002233 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2234 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002235 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2236 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002237
Paul Jensen85cf78e2015-06-25 13:25:07 -04002238 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002239 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002240 for (int i = 0; i < networkCallbacks.length; i++) {
2241 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2242 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002243 testFactory.waitForNetworkRequests(expectedRequestCount);
2244 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002245
Paul Jensen85cf78e2015-06-25 13:25:07 -04002246 // Drop the higher scored network.
2247 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002248 // With the default network disconnecting, the requests are sent with score 0 to factories.
2249 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002250 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002251 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002252 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002253 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2254 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002255
2256 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002257 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002258 handlerThread.quit();
2259 }
2260
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002261 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002262 public void testNetworkFactoryRequests() throws Exception {
2263 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2264 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2265 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2266 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2267 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2268 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2269 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2270 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2271 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2272 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2273 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2274 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2275 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2276 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2277 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2278 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2279 }
2280
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002281 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002282 public void testNoMutableNetworkRequests() throws Exception {
2283 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002284 NetworkRequest request1 = new NetworkRequest.Builder()
2285 .addCapability(NET_CAPABILITY_VALIDATED)
2286 .build();
2287 NetworkRequest request2 = new NetworkRequest.Builder()
2288 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2289 .build();
2290
2291 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002292 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2293 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2294 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2295 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002296 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002297
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002298 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002299 public void testMMSonWiFi() throws Exception {
2300 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002301 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002302 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002303 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002304 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002305 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002306 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002307 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002308
Paul Jensene0988542015-06-25 15:30:08 -04002309 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002310 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09002311 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002312 mWiFiNetworkAgent.connect(true);
2313 waitFor(cv);
2314 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002315
Paul Jensene0988542015-06-25 15:30:08 -04002316 // Register MMS NetworkRequest
2317 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2318 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2319 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2320 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002321
Paul Jensene0988542015-06-25 15:30:08 -04002322 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002323 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002324 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002325 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002326 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002327 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002328
Paul Jensene0988542015-06-25 15:30:08 -04002329 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002330 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002331 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002332 verifyActiveNetwork(TRANSPORT_WIFI);
2333 }
2334
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002335 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002336 public void testMMSonCell() throws Exception {
2337 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002338 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09002339 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002340 mCellNetworkAgent.connect(false);
2341 waitFor(cv);
2342 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002343
Paul Jensene0988542015-06-25 15:30:08 -04002344 // Register MMS NetworkRequest
2345 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2346 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2347 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2348 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002349
Paul Jensene0988542015-06-25 15:30:08 -04002350 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002351 TestNetworkAgentWrapper
2352 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002353 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2354 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002355 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002356 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002357
Paul Jensene0988542015-06-25 15:30:08 -04002358 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002359 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002360 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002361 verifyActiveNetwork(TRANSPORT_CELLULAR);
2362 }
2363
lucaslinf3b59b32019-03-26 17:49:49 +08002364 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002365 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002366 // Register network callback.
2367 NetworkRequest request = new NetworkRequest.Builder()
2368 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2369 .build();
2370 TestNetworkCallback callback = new TestNetworkCallback();
2371 mCm.registerNetworkCallback(request, callback);
2372
2373 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002374 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002375 mCellNetworkAgent.connect(true);
2376 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2377
2378 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002379 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002380 mWiFiNetworkAgent.connectWithPartialConnectivity();
2381 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2382 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2383
2384 // Mobile data should be the default network.
2385 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2386 callback.assertNoCallback();
2387
lucaslinf3b59b32019-03-26 17:49:49 +08002388 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2389 // probe.
lucaslin783f2212019-10-22 18:27:33 +08002390 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
lucasline252a742019-03-12 13:08:03 +08002391 // If the user chooses yes to use this partial connectivity wifi, switch the default
2392 // network to wifi and check if wifi becomes valid or not.
2393 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2394 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002395 // If user accepts partial connectivity network,
2396 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002397 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002398 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002399
lucaslinf3b59b32019-03-26 17:49:49 +08002400 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2401 // validated.
2402 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002403 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002404 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2405 mWiFiNetworkAgent);
2406 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2407 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2408
2409 // Disconnect and reconnect wifi with partial connectivity again.
2410 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002411 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002412 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002413 mWiFiNetworkAgent.connectWithPartialConnectivity();
2414 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2415 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2416
2417 // Mobile data should be the default network.
2418 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2419
2420 // If the user chooses no, disconnect wifi immediately.
2421 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2422 false /* always */);
Chalard Jean059c4262019-09-30 17:51:12 +09002423 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002424
2425 // If user accepted partial connectivity before, and device reconnects to that network
2426 // again, but now the network has full connectivity. The network shouldn't contain
2427 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002428 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002429 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002430 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2431 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002432 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002433
lucaslinf3b59b32019-03-26 17:49:49 +08002434 // If user accepted partial connectivity network before,
2435 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2436 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002437 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002438 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002439 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002440 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2441 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002442
lucasline252a742019-03-12 13:08:03 +08002443 // Wifi should be the default network.
2444 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2445 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002446 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002447
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002448 // The user accepted partial connectivity and selected "don't ask again". Now the user
2449 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2450 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002451 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002452 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2453 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002454 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002455 // If user accepted partial connectivity network before,
2456 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2457 // ConnectivityService#updateNetworkInfo().
lucaslinf3b59b32019-03-26 17:49:49 +08002458 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002459 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002460 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002461 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002462 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
lucaslin783f2212019-10-22 18:27:33 +08002463 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002464
lucaslinf3b59b32019-03-26 17:49:49 +08002465 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2466 // validated.
2467 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2468 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2469 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002470 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002471
2472 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2473 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002474 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002475 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2476 true /* acceptUnvalidated */);
2477
2478 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2479 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2480 // notifyNetworkConnected.
lucaslin783f2212019-10-22 18:27:33 +08002481 mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002482 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002483 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002484 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002485 callback.expectCapabilitiesWith(
2486 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2487 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002488 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002489 }
2490
2491 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002492 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002493 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2494 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2495 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2496 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2497
2498 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2499 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2500 .addCapability(NET_CAPABILITY_VALIDATED).build();
2501 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2502
2503 // Bring up a network with a captive portal.
2504 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002505 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002506 String redirectUrl = "http://android.com/path";
lucaslin783f2212019-10-22 18:27:33 +08002507 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002508 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002509 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002510
2511 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2512 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2513 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2514 .launchCaptivePortalApp();
2515
2516 // Report that the captive portal is dismissed with partial connectivity, and check that
2517 // callbacks are fired.
2518 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002519 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002520 waitForIdle();
2521 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2522 mWiFiNetworkAgent);
2523
2524 // Report partial connectivity is accepted.
lucaslin783f2212019-10-22 18:27:33 +08002525 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002526 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2527 false /* always */);
2528 waitForIdle();
2529 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002530 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002531 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2532 NetworkCapabilities nc =
2533 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2534 mWiFiNetworkAgent);
2535
2536 mCm.unregisterNetworkCallback(captivePortalCallback);
2537 mCm.unregisterNetworkCallback(validatedCallback);
2538 }
2539
2540 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002541 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002542 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2543 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2544 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2545 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2546
2547 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2548 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2549 .addCapability(NET_CAPABILITY_VALIDATED).build();
2550 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002551
2552 // Bring up a network with a captive portal.
2553 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002554 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002555 String firstRedirectUrl = "http://example.com/firstPath";
lucaslin783f2212019-10-22 18:27:33 +08002556 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002557 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002558 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002559
2560 // Take down network.
2561 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002562 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002563 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002564
2565 // Bring up a network with a captive portal.
2566 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002567 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002568 String secondRedirectUrl = "http://example.com/secondPath";
lucaslin783f2212019-10-22 18:27:33 +08002569 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002570 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002571 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002572
2573 // Make captive portal disappear then revalidate.
2574 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
lucaslin783f2212019-10-22 18:27:33 +08002575 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002576 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002577 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002578
2579 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002580 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002581 // Expect no notification to be shown when captive portal disappears by itself
2582 verify(mNotificationManager, never()).notifyAsUser(
2583 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002584
2585 // Break network connectivity.
2586 // Expect NET_CAPABILITY_VALIDATED onLost callback.
lucaslin783f2212019-10-22 18:27:33 +08002587 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002588 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean059c4262019-09-30 17:51:12 +09002589 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002590 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002591
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002592 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002593 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002594 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2595 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2596 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2597 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2598
2599 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2600 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2601 .addCapability(NET_CAPABILITY_VALIDATED).build();
2602 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2603
2604 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002605 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002606 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002607 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002608 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2609
2610 // Check that calling startCaptivePortalApp does nothing.
2611 final int fastTimeoutMs = 100;
2612 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002613 waitForIdle();
2614 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002615 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2616
2617 // Turn into a captive portal.
lucaslin783f2212019-10-22 18:27:33 +08002618 mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002619 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002620 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002621 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002622
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002623 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002624 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002625 waitForIdle();
2626 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2627
2628 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2629 final Bundle testBundle = new Bundle();
2630 final String testKey = "testkey";
2631 final String testValue = "testvalue";
2632 testBundle.putString(testKey, testValue);
2633 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2634 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2635 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2636 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002637
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002638 // Report that the captive portal is dismissed, and check that callbacks are fired
lucaslin783f2212019-10-22 18:27:33 +08002639 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002640 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002641 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002642 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002643 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2644 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002645
2646 mCm.unregisterNetworkCallback(validatedCallback);
2647 mCm.unregisterNetworkCallback(captivePortalCallback);
2648 }
2649
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002650 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002651 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002652 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2653 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2654 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2655 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2656
2657 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2658 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2659 .addCapability(NET_CAPABILITY_VALIDATED).build();
2660 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2661
2662 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2663 // Bring up a network with a captive portal.
2664 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002665 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002666 String firstRedirectUrl = "http://example.com/firstPath";
2667
lucaslin783f2212019-10-22 18:27:33 +08002668 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002669 mWiFiNetworkAgent.expectDisconnected();
2670 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002671
2672 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002673 }
2674
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002675 private NetworkRequest.Builder newWifiRequestBuilder() {
2676 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2677 }
2678
Etan Cohen836ad572018-12-30 17:59:59 -08002679 /**
2680 * Verify request matching behavior with network specifiers.
2681 *
2682 * Note: this test is somewhat problematic since it involves removing capabilities from
2683 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2684 * as a WTF bug in
2685 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2686 * does work.
2687 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002688 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002689 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002690 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2691 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2692 Parcelable {
2693 @Override
2694 public boolean satisfiedBy(NetworkSpecifier other) {
2695 return true;
2696 }
2697
2698 @Override
2699 public int describeContents() {
2700 return 0;
2701 }
2702
2703 @Override
2704 public void writeToParcel(Parcel dest, int flags) {}
2705
2706 @Override
2707 public NetworkSpecifier redact() {
2708 return null;
2709 }
2710 }
2711
2712 // A network specifier that matches either another LocalNetworkSpecifier with the same
2713 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2714 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2715 private String mString;
2716
2717 LocalStringNetworkSpecifier(String string) {
2718 mString = string;
2719 }
2720
2721 @Override
2722 public boolean satisfiedBy(NetworkSpecifier other) {
2723 if (other instanceof LocalStringNetworkSpecifier) {
2724 return TextUtils.equals(mString,
2725 ((LocalStringNetworkSpecifier) other).mString);
2726 }
2727 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2728 return false;
2729 }
2730
2731 @Override
2732 public int describeContents() {
2733 return 0;
2734 }
2735 @Override
2736 public void writeToParcel(Parcel dest, int flags) {}
2737 }
2738
2739
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002740 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002741 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002742 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002743 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2744 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002745 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2746 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002747 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002748 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002749
2750 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2751 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2752 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002753 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002754 TestNetworkCallback cFoo = new TestNetworkCallback();
2755 TestNetworkCallback cBar = new TestNetworkCallback();
2756 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002757 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002758
2759 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2760 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2761 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002762 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002763 mCm.registerNetworkCallback(rFoo, cFoo);
2764 mCm.registerNetworkCallback(rBar, cBar);
2765
Etan Cohen836ad572018-12-30 17:59:59 -08002766 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2767 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2768
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002769 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002770 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002771 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2772 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2773 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2774 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002775 assertNoCallbacks(cFoo, cBar);
2776
Etan Cohen836ad572018-12-30 17:59:59 -08002777 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002778 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002779 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002780 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2781 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002782 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002783 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2784 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08002785 assertEquals(nsFoo,
2786 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002787 cFoo.assertNoCallback();
2788
Etan Cohen836ad572018-12-30 17:59:59 -08002789 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean059c4262019-09-30 17:51:12 +09002790 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002791 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002792 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002793 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2794 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002795 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002796 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2797 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08002798 assertEquals(nsBar,
2799 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2800 cBar.assertNoCallback();
2801
2802 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2803 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2804 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002805 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2806 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002807 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002808 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2809 (caps) -> caps.getNetworkSpecifier() == null);
2810 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2811 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002812 assertNull(
2813 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2814 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002815 cBar.assertNoCallback();
2816
2817 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean059c4262019-09-30 17:51:12 +09002818 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2819 cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002820 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean059c4262019-09-30 17:51:12 +09002821 c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002822 }
2823
Etan Cohen836ad572018-12-30 17:59:59 -08002824 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002825 }
2826
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002827 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002828 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09002829 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002830 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002831 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09002832 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002833
Chalard Jean751bb3f2019-06-19 23:29:58 +09002834 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002835 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2836 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002837 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002838 mService.requestNetwork(networkCapabilities, null, 0, null,
2839 ConnectivityManager.TYPE_WIFI);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002840 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002841
Etan Cohena7434272017-04-03 12:17:51 -07002842 class NonParcelableSpecifier extends NetworkSpecifier {
2843 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2844 };
2845 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2846 @Override public int describeContents() { return 0; }
2847 @Override public void writeToParcel(Parcel p, int flags) {}
2848 }
Etan Cohena7434272017-04-03 12:17:51 -07002849
Chalard Jean751bb3f2019-06-19 23:29:58 +09002850 final NetworkRequest.Builder builder =
2851 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2852 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002853 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2854 Parcel parcelW = Parcel.obtain();
2855 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002856 });
Etan Cohena7434272017-04-03 12:17:51 -07002857
Chalard Jean751bb3f2019-06-19 23:29:58 +09002858 final NetworkRequest nr =
2859 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
2860 .setNetworkSpecifier(new ParcelableSpecifier())
2861 .build();
Etan Cohena7434272017-04-03 12:17:51 -07002862 assertNotNull(nr);
2863
Chalard Jean751bb3f2019-06-19 23:29:58 +09002864 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002865 Parcel parcelW = Parcel.obtain();
2866 nr.writeToParcel(parcelW, 0);
2867 byte[] bytes = parcelW.marshall();
2868 parcelW.recycle();
2869
2870 Parcel parcelR = Parcel.obtain();
2871 parcelR.unmarshall(bytes, 0, bytes.length);
2872 parcelR.setDataPosition(0);
2873 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002874 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002875 }
2876
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002877 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002878 public void testNetworkSpecifierUidSpoofSecurityException() throws Exception {
Etan Cohen859748f2017-04-03 17:42:34 -07002879 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2880 @Override
2881 public boolean satisfiedBy(NetworkSpecifier other) {
2882 return true;
2883 }
2884
2885 @Override
2886 public void assertValidFromUid(int requestorUid) {
2887 throw new SecurityException("failure");
2888 }
2889
2890 @Override
2891 public int describeContents() { return 0; }
2892 @Override
2893 public void writeToParcel(Parcel dest, int flags) {}
2894 }
2895
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002896 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07002897 mWiFiNetworkAgent.connect(false);
2898
2899 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
2900 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
2901 networkSpecifier).build();
2902 TestNetworkCallback networkCallback = new TestNetworkCallback();
Chalard Jean751bb3f2019-06-19 23:29:58 +09002903 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07002904 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002905 });
Etan Cohen859748f2017-04-03 17:42:34 -07002906 }
2907
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002908 @Test
paulhu3d67f532019-03-22 16:35:06 +08002909 public void testInvalidSignalStrength() {
2910 NetworkRequest r = new NetworkRequest.Builder()
2911 .addCapability(NET_CAPABILITY_INTERNET)
2912 .addTransportType(TRANSPORT_WIFI)
2913 .setSignalStrength(-75)
2914 .build();
2915 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
2916 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09002917 assertThrows(SecurityException.class, () ->
2918 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08002919
Chalard Jean751bb3f2019-06-19 23:29:58 +09002920 assertThrows(SecurityException.class, () ->
2921 mCm.registerNetworkCallback(r, PendingIntent.getService(
2922 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08002923
2924 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09002925 assertThrows(IllegalArgumentException.class, () ->
2926 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08002927
Chalard Jean751bb3f2019-06-19 23:29:58 +09002928 assertThrows(IllegalArgumentException.class, () ->
2929 mCm.requestNetwork(r, PendingIntent.getService(
2930 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08002931 }
2932
2933 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09002934 public void testRegisterDefaultNetworkCallback() throws Exception {
2935 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
2936 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
2937 defaultNetworkCallback.assertNoCallback();
2938
2939 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
2940 // whenever Wi-Fi is up. Without this, the mobile network agent is
2941 // reaped before any other activity can take place.
2942 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
2943 final NetworkRequest cellRequest = new NetworkRequest.Builder()
2944 .addTransportType(TRANSPORT_CELLULAR).build();
2945 mCm.requestNetwork(cellRequest, cellNetworkCallback);
2946 cellNetworkCallback.assertNoCallback();
2947
2948 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002949 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09002950 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002951 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2952 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002953 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002954
2955 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002956 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09002957 mWiFiNetworkAgent.connect(true);
2958 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002959 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002960 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002961
2962 // Bring down cell. Expect no default network callback, since it wasn't the default.
2963 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002964 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002965 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002966 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002967
2968 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002969 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09002970 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002971 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002972 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002973 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09002974
2975 // Bring down wifi. Expect the default network callback to notified of LOST wifi
2976 // followed by AVAILABLE cell.
2977 mWiFiNetworkAgent.disconnect();
2978 cellNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09002979 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002980 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09002981 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002982 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2983 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002984 waitForIdle();
2985 assertEquals(null, mCm.getActiveNetwork());
2986
2987 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002988 final TestNetworkAgentWrapper
2989 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002990 final ArraySet<UidRange> ranges = new ArraySet<>();
2991 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002992 mMockVpn.setNetworkAgent(vpnNetworkAgent);
2993 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002994 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09002995 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002996 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
2997 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
2998
2999 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003000 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003001 waitForIdle();
3002 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003003 }
3004
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003005 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003006 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003007 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003008 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003009 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3010 .addTransportType(TRANSPORT_CELLULAR).build();
3011 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3012
3013 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003014 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09003015 mCellNetworkAgent.connect(true);
3016
Erik Kline1d3db322017-02-28 16:20:20 +09003017 // We should get onAvailable(), onCapabilitiesChanged(), and
3018 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3019 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003020 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003021 cellNetworkCallback.assertNoCallback();
3022
3023 // Update LinkProperties.
3024 final LinkProperties lp = new LinkProperties();
3025 lp.setInterfaceName("foonet_data0");
3026 mCellNetworkAgent.sendLinkProperties(lp);
3027 // We should get onLinkPropertiesChanged().
Chalard Jean059c4262019-09-30 17:51:12 +09003028 cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Chalard Jean6f4216f2019-06-05 01:40:32 +09003029 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003030 cellNetworkCallback.assertNoCallback();
3031
Erik Kline1d3db322017-02-28 16:20:20 +09003032 // Suspend the network.
3033 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003034 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3035 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003036 cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003037 cellNetworkCallback.assertNoCallback();
3038
Erik Klineacdd6392016-07-07 16:50:58 +09003039 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003040 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003041 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003042 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3043 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003044 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003045 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003046 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3047
3048 mCellNetworkAgent.resume();
3049 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3050 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003051 cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09003052 cellNetworkCallback.assertNoCallback();
3053
3054 dfltNetworkCallback = new TestNetworkCallback();
3055 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3056 // This time onNetworkSuspended should not be called.
3057 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3058 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003059
Erik Klineacdd6392016-07-07 16:50:58 +09003060 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3061 mCm.unregisterNetworkCallback(cellNetworkCallback);
3062 }
3063
Calvin On1f64f3f2016-10-11 15:10:46 -07003064 private void setCaptivePortalMode(int mode) {
3065 ContentResolver cr = mServiceContext.getContentResolver();
3066 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3067 }
3068
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003069 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003070 ContentResolver cr = mServiceContext.getContentResolver();
3071 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003072 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003073 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003074 }
3075
Erik Kline79c6d052018-03-21 07:18:33 -07003076 private void setPrivateDnsSettings(String mode, String specifier) {
3077 final ContentResolver cr = mServiceContext.getContentResolver();
3078 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3079 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3080 mService.updatePrivateDnsSettings();
3081 waitForIdle();
3082 }
3083
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003084 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003085 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3086 assertNotNull(nc);
3087 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3088 }
3089
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003090 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003091 public void testBackgroundNetworks() throws Exception {
3092 // Create a background request. We can't do this ourselves because ConnectivityService
3093 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003094 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08003095 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003096 final NetworkRequest request = new NetworkRequest.Builder().build();
3097 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3098 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3099 final TestNetworkCallback callback = new TestNetworkCallback();
3100 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3101 mCm.registerNetworkCallback(request, callback);
3102 mCm.registerNetworkCallback(fgRequest, fgCallback);
3103
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003104 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003105 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003106 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3107 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003108 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3109
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003110 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003111 mWiFiNetworkAgent.connect(true);
3112
3113 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003114 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003115 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003116 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003117 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003118 fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003119 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003120 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3121 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3122
3123 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003124 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003125 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09003126 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003127 // Expect a network capabilities update sans FOREGROUND.
3128 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003129 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3130 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3131
3132 // File a cell request and check that cell comes into the foreground.
3133 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3134 .addTransportType(TRANSPORT_CELLULAR).build();
3135 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3136 mCm.requestNetwork(cellRequest, cellCallback);
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.
Chalard Jean28e6b262019-11-19 21:30:44 +09003141 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003142 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003143 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3144 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3145
3146 // Release the request. The network immediately goes into the background, since it was not
3147 // lingering.
3148 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09003149 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003150 // Expect a network capabilities update sans FOREGROUND.
3151 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003152 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3153 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3154
3155 // Disconnect wifi and check that cell is foreground again.
3156 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003157 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3158 fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003159 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003160 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3161
3162 mCm.unregisterNetworkCallback(callback);
3163 mCm.unregisterNetworkCallback(fgCallback);
3164 }
3165
Hugo Benichi849b81b2017-05-25 13:42:31 +09003166 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003167 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003168 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003169 // Benchmarks connecting and switching performance in the presence of a large number of
3170 // NetworkRequests.
3171 // 1. File NUM_REQUESTS requests.
3172 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3173 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3174 // and NUM_REQUESTS onAvailable callbacks to fire.
3175 // See how long it took.
3176 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003177 final int REGISTER_TIME_LIMIT_MS = 200;
3178 final int CONNECT_TIME_LIMIT_MS = 60;
3179 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003180 final int UNREGISTER_TIME_LIMIT_MS = 20;
3181
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003182 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3183 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3184 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3185 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3186
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003187 for (int i = 0; i < NUM_REQUESTS; i++) {
3188 callbacks[i] = new NetworkCallback() {
3189 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3190 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3191 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003192 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003193
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003194 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003195 for (NetworkCallback cb : callbacks) {
3196 mCm.registerNetworkCallback(request, cb);
3197 }
3198 });
3199
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003200 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003201 // Don't request that the network validate, because otherwise connect() will block until
3202 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3203 // and we won't actually measure anything.
3204 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003205
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003206 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003207 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003208 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003209 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3210 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3211 onAvailableDispatchingDuration));
3212 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3213 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3214 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003215
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003216 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003217 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003218 mWiFiNetworkAgent.adjustScore(40);
3219 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003220
3221 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003222 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003223 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003224 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3225 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3226 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3227 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3228 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003229
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003230 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003231 for (NetworkCallback cb : callbacks) {
3232 mCm.unregisterNetworkCallback(cb);
3233 }
3234 });
3235 }
3236
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003237 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003238 public void testMobileDataAlwaysOn() throws Exception {
paulhu86e23eb2019-11-05 18:05:05 +08003239 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003240 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3241 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3242 .addTransportType(TRANSPORT_CELLULAR).build();
3243 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3244
3245 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3246 handlerThread.start();
3247 NetworkCapabilities filter = new NetworkCapabilities()
3248 .addTransportType(TRANSPORT_CELLULAR)
3249 .addCapability(NET_CAPABILITY_INTERNET);
3250 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3251 mServiceContext, "testFactory", filter);
3252 testFactory.setScoreFilter(40);
3253
3254 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003255 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003256 testFactory.register();
3257 testFactory.waitForNetworkRequests(1);
3258 assertTrue(testFactory.getMyStartRequested());
3259
3260 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003261 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003262 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3263 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003264 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003265 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003266 assertFalse(testFactory.getMyStartRequested());
3267
3268 ContentResolver cr = mServiceContext.getContentResolver();
3269
3270 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003271 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003272 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003273 testFactory.waitForNetworkRequests(2);
3274 assertTrue(testFactory.getMyStartRequested());
3275
3276 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003277 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003278 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003279 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003280 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003281 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003282 testFactory.waitForNetworkRequests(2);
3283 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3284
3285 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003286 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003287 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003288 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003289
3290 // Turn off mobile data always on and expect the request to disappear...
3291 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003292 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003293 testFactory.waitForNetworkRequests(1);
3294
3295 // ... and cell data to be torn down.
Chalard Jean059c4262019-09-30 17:51:12 +09003296 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003297 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003298
3299 testFactory.unregister();
3300 mCm.unregisterNetworkCallback(cellNetworkCallback);
3301 handlerThread.quit();
3302 }
3303
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003304 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003305 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003306 final ContentResolver cr = mServiceContext.getContentResolver();
3307 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3308
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003309 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003310 String[] values = new String[] {null, "0", "1"};
3311 for (int i = 0; i < values.length; i++) {
3312 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003313 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003314 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003315 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003316 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003317 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003318 }
3319
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003320 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003321
3322 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003323 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003324 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003325 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003326 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003327
3328 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003329 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003330 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003331 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003332 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003333
3334 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003335 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003336 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003337 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003338 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003339 }
3340
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003341 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003342 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003343 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003344
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003345 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003346 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003347
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003348 // File a request for cell to ensure it doesn't go down.
3349 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3350 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3351 .addTransportType(TRANSPORT_CELLULAR).build();
3352 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3353
3354 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3355 mCm.registerDefaultNetworkCallback(defaultCallback);
3356
3357 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3358 .addTransportType(TRANSPORT_WIFI)
3359 .addCapability(NET_CAPABILITY_VALIDATED)
3360 .build();
3361 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3362 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3363
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003364 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003365 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003366
3367 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003368 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003369 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003370 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3371 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003372 Network cellNetwork = mCellNetworkAgent.getNetwork();
3373
3374 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003375 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003376 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003377 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3378 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003379 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3380
3381 // Fail validation on wifi.
lucaslin783f2212019-10-22 18:27:33 +08003382 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003383 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003384 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003385 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003386
3387 // Because avoid bad wifi is off, we don't switch to cellular.
3388 defaultCallback.assertNoCallback();
3389 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3390 NET_CAPABILITY_VALIDATED));
3391 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3392 NET_CAPABILITY_VALIDATED));
3393 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3394
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003395 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3396 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003397 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3398 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003399 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003400 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3401
3402 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003403 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3404 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003405 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003406 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3407
3408 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3409 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003410 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003411 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3412 NET_CAPABILITY_VALIDATED));
3413 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3414 NET_CAPABILITY_VALIDATED));
3415 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3416
3417 // Disconnect and reconnect wifi to clear the one-time switch above.
3418 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003419 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003420 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003421 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3422 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003423 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3424
3425 // Fail validation on wifi and expect the dialog to appear.
lucaslin783f2212019-10-22 18:27:33 +08003426 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003427 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003428 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003429 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003430
3431 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003432 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003433 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003434
3435 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003436 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003437 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3438 NET_CAPABILITY_VALIDATED));
3439 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3440 NET_CAPABILITY_VALIDATED));
3441 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3442
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003443 // Simulate the user turning the cellular fallback setting off and then on.
3444 // We switch to wifi and then to cell.
3445 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003446 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003447 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003448 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3449 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003450 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003451 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003452 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3453
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003454 // If cell goes down, we switch to wifi.
3455 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003456 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003457 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003458 validatedWifiCallback.assertNoCallback();
3459
3460 mCm.unregisterNetworkCallback(cellNetworkCallback);
3461 mCm.unregisterNetworkCallback(validatedWifiCallback);
3462 mCm.unregisterNetworkCallback(defaultCallback);
3463 }
3464
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003465 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003466 public void testMeteredMultipathPreferenceSetting() throws Exception {
3467 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003468 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3469
3470 for (int config : Arrays.asList(0, 3, 2)) {
3471 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003472 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003473 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003474 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003475 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003476
3477 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3478 String msg = String.format("config=%d, setting=%s", config, setting);
3479 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3480 }
3481 }
3482 }
3483
Erik Kline3841a482015-11-25 12:49:38 +09003484 /**
3485 * Validate that a satisfied network request does not trigger onUnavailable() once the
3486 * time-out period expires.
3487 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003488 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003489 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003490 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3491 NetworkCapabilities.TRANSPORT_WIFI).build();
3492 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003493 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003494
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003495 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003496 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003497 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003498 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003499
3500 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003501 networkCallback.assertNoCallback();
3502 }
3503
3504 /**
3505 * Validate that a satisfied network request followed by a disconnected (lost) network does
3506 * not trigger onUnavailable() once the time-out period expires.
3507 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003508 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003509 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003510 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3511 NetworkCapabilities.TRANSPORT_WIFI).build();
3512 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003513 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003514
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003515 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003516 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003517 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003518 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003519 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003520 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003521
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003522 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003523 networkCallback.assertNoCallback();
3524 }
3525
3526 /**
3527 * Validate that when a time-out is specified for a network request the onUnavailable()
3528 * callback is called when time-out expires. Then validate that if network request is
3529 * (somehow) satisfied - the callback isn't called later.
3530 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003531 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003532 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003533 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3534 NetworkCapabilities.TRANSPORT_WIFI).build();
3535 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003536 final int timeoutMs = 10;
3537 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003538
3539 // pass timeout and validate that UNAVAILABLE is called
Chalard Jean059c4262019-09-30 17:51:12 +09003540 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Erik Kline3841a482015-11-25 12:49:38 +09003541
3542 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003543 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003544 mWiFiNetworkAgent.connect(false);
3545 networkCallback.assertNoCallback();
3546 }
3547
3548 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003549 * Validate that when a network request is unregistered (cancelled), no posterior event can
3550 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003551 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003552 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003553 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003554 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3555 NetworkCapabilities.TRANSPORT_WIFI).build();
3556 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003557 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003558
Hugo Benichidfb559a2016-12-20 14:57:49 +09003559 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003560 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003561 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3562 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003563 networkCallback.assertNoCallback();
3564
3565 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003566 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003567 mWiFiNetworkAgent.connect(false);
3568 networkCallback.assertNoCallback();
3569 }
3570
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003571 @Test
3572 public void testUnfulfillableNetworkRequest() throws Exception {
3573 runUnfulfillableNetworkRequest(false);
3574 }
3575
3576 @Test
3577 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3578 runUnfulfillableNetworkRequest(true);
3579 }
3580
Etan Cohenddb720a2019-01-08 12:09:18 -08003581 /**
3582 * Validate the callback flow for a factory releasing a request as unfulfillable.
3583 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003584 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003585 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3586 NetworkCapabilities.TRANSPORT_WIFI).build();
3587 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3588
3589 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3590 handlerThread.start();
3591 NetworkCapabilities filter = new NetworkCapabilities()
3592 .addTransportType(TRANSPORT_WIFI)
3593 .addCapability(NET_CAPABILITY_INTERNET);
3594 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3595 mServiceContext, "testFactory", filter);
3596 testFactory.setScoreFilter(40);
3597
3598 // Register the factory and expect it to receive the default request.
Etan Cohenae574a82019-01-08 12:09:18 -08003599 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003600 testFactory.register();
3601 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3602
3603 assertEquals(1, requests.size()); // have 1 request at this point
3604 int origRequestId = requests.valueAt(0).requestId;
3605
3606 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003607 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003608 mCm.requestNetwork(nr, networkCallback);
3609 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3610
3611 int newRequestId = 0;
3612 for (int i = 0; i < requests.size(); ++i) {
3613 if (requests.valueAt(i).requestId != origRequestId) {
3614 newRequestId = requests.valueAt(i).requestId;
3615 break;
3616 }
3617 }
3618
Etan Cohen22e0fc12019-05-23 08:16:20 -07003619 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003620 if (preUnregister) {
3621 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003622
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003623 // Simulate the factory releasing the request as unfulfillable: no-op since
3624 // the callback has already been unregistered (but a test that no exceptions are
3625 // thrown).
3626 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3627 } else {
3628 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003629 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3630
Chalard Jean059c4262019-09-30 17:51:12 +09003631 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003632 testFactory.waitForRequests();
3633
3634 // unregister network callback - a no-op (since already freed by the
3635 // on-unavailable), but should not fail or throw exceptions.
3636 mCm.unregisterNetworkCallback(networkCallback);
3637 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003638
Etan Cohenddb720a2019-01-08 12:09:18 -08003639 testFactory.unregister();
3640 handlerThread.quit();
3641 }
3642
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003643 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3644
Chalard Jeane7b24752019-06-20 16:01:19 +09003645 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003646
3647 private class CallbackValue {
3648 public CallbackType callbackType;
3649 public int error;
3650
3651 public CallbackValue(CallbackType type) {
3652 this.callbackType = type;
3653 this.error = PacketKeepalive.SUCCESS;
3654 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3655 }
3656
3657 public CallbackValue(CallbackType type, int error) {
3658 this.callbackType = type;
3659 this.error = error;
3660 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3661 }
3662
3663 @Override
3664 public boolean equals(Object o) {
3665 return o instanceof CallbackValue &&
3666 this.callbackType == ((CallbackValue) o).callbackType &&
3667 this.error == ((CallbackValue) o).error;
3668 }
3669
3670 @Override
3671 public String toString() {
3672 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3673 }
3674 }
3675
junyulai7c469172019-01-16 20:23:34 +08003676 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003677
3678 @Override
3679 public void onStarted() {
3680 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3681 }
3682
3683 @Override
3684 public void onStopped() {
3685 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3686 }
3687
3688 @Override
3689 public void onError(int error) {
3690 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3691 }
3692
Chalard Jeane7b24752019-06-20 16:01:19 +09003693 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3694 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003695 }
3696
Chalard Jeane7b24752019-06-20 16:01:19 +09003697 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003698 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3699 }
3700
Chalard Jeane7b24752019-06-20 16:01:19 +09003701 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003702 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3703 }
3704
Chalard Jeane7b24752019-06-20 16:01:19 +09003705 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003706 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3707 }
3708 }
3709
junyulai48eac1d42018-12-27 17:25:29 +08003710 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3711
3712 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3713
3714 private class CallbackValue {
3715 public CallbackType callbackType;
3716 public int error;
3717
3718 CallbackValue(CallbackType type) {
3719 this.callbackType = type;
3720 this.error = SocketKeepalive.SUCCESS;
3721 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3722 }
3723
3724 CallbackValue(CallbackType type, int error) {
3725 this.callbackType = type;
3726 this.error = error;
3727 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3728 }
3729
3730 @Override
3731 public boolean equals(Object o) {
3732 return o instanceof CallbackValue
3733 && this.callbackType == ((CallbackValue) o).callbackType
3734 && this.error == ((CallbackValue) o).error;
3735 }
3736
3737 @Override
3738 public String toString() {
3739 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3740 error);
3741 }
3742 }
3743
3744 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003745 private final Executor mExecutor;
3746
3747 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3748 mExecutor = executor;
3749 }
junyulai48eac1d42018-12-27 17:25:29 +08003750
3751 @Override
3752 public void onStarted() {
3753 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3754 }
3755
3756 @Override
3757 public void onStopped() {
3758 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3759 }
3760
3761 @Override
3762 public void onError(int error) {
3763 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3764 }
3765
Chalard Jeane7b24752019-06-20 16:01:19 +09003766 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3767 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3768
junyulai48eac1d42018-12-27 17:25:29 +08003769 }
3770
Chalard Jeane7b24752019-06-20 16:01:19 +09003771 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003772 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3773 }
3774
Chalard Jeane7b24752019-06-20 16:01:19 +09003775 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003776 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3777 }
3778
Chalard Jeane7b24752019-06-20 16:01:19 +09003779 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003780 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3781 }
junyulai7c469172019-01-16 20:23:34 +08003782
3783 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003784 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08003785 CallbackValue cv = mCallbacks.peek();
3786 assertNull("Unexpected callback: " + cv, cv);
3787 }
junyulai48eac1d42018-12-27 17:25:29 +08003788 }
3789
Chalard Jeane7b24752019-06-20 16:01:19 +09003790 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003791 // Ensure the network is disconnected before we do anything.
3792 if (mWiFiNetworkAgent != null) {
3793 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3794 }
3795
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003796 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09003797 ConditionVariable cv = registerConnectivityBroadcast(1);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003798 mWiFiNetworkAgent.connect(true);
3799 waitFor(cv);
3800 verifyActiveNetwork(TRANSPORT_WIFI);
3801 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003802 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003803 return mWiFiNetworkAgent.getNetwork();
3804 }
3805
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003806 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07003807 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003808 public void testPacketKeepalives() throws Exception {
3809 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3810 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3811 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3812 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3813 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3814
Nathan Harold63dd8132018-02-14 13:09:45 -08003815 final int validKaInterval = 15;
3816 final int invalidKaInterval = 9;
3817
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003818 LinkProperties lp = new LinkProperties();
3819 lp.setInterfaceName("wlan12");
3820 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3821 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3822 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3823 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3824
3825 Network notMyNet = new Network(61234);
3826 Network myNet = connectKeepaliveNetwork(lp);
3827
3828 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3829 PacketKeepalive ka;
3830
3831 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003832 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003833 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3834
Nathan Harold63dd8132018-02-14 13:09:45 -08003835 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003836 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3837
Nathan Harold63dd8132018-02-14 13:09:45 -08003838 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003839 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3840
Nathan Harold63dd8132018-02-14 13:09:45 -08003841 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003842 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3843
Nathan Harold63dd8132018-02-14 13:09:45 -08003844 // NAT-T is only supported for IPv4.
3845 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3846 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003847
Nathan Harold63dd8132018-02-14 13:09:45 -08003848 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003849 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3850
Nathan Harold63dd8132018-02-14 13:09:45 -08003851 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003852 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3853
Nathan Harold63dd8132018-02-14 13:09:45 -08003854 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003855 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3856
Nathan Harold63dd8132018-02-14 13:09:45 -08003857 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003858 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3859
3860 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003861 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003862 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003863 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003864 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003865 ka.stop();
3866 callback.expectStopped();
3867
3868 // Check that deleting the IP address stops the keepalive.
3869 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003870 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003871 callback.expectStarted();
3872 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3873 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3874 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3875 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3876 mWiFiNetworkAgent.sendLinkProperties(lp);
3877
3878 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003879 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003880 callback.expectStarted();
3881 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003882 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003883 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3884
3885 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003886 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003887 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003888 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003889 ka.stop();
3890
3891 // Reconnect.
3892 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003893 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003894
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003895 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3896 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003897 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003898 callback.expectStarted();
3899
3900 // The second one gets slot 2.
3901 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
3902 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003903 PacketKeepalive ka2 = mCm.startNattKeepalive(
3904 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003905 callback2.expectStarted();
3906
3907 // Now stop the first one and create a third. This also gets slot 1.
3908 ka.stop();
3909 callback.expectStopped();
3910
3911 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
3912 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08003913 PacketKeepalive ka3 = mCm.startNattKeepalive(
3914 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003915 callback3.expectStarted();
3916
3917 ka2.stop();
3918 callback2.expectStopped();
3919
3920 ka3.stop();
3921 callback3.expectStopped();
3922 }
Udam Sainib7c24872016-01-04 12:16:14 -08003923
Xiao Maa4637112019-02-07 15:03:57 +09003924 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09003925 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
3926 throws Exception {
junyulai06835112019-01-03 18:50:15 +08003927 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09003928 final Executor executorInline = (Runnable r) -> r.run();
3929 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08003930 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09003931 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003932 }
junyulai06835112019-01-03 18:50:15 +08003933
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09003934 @Test
junyulaiafe9b492019-03-19 18:50:23 +08003935 public void testNattSocketKeepalives() throws Exception {
3936 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
3937 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08003938 }
3939
3940 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08003941 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08003942 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08003943 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08003944 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3945 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3946 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3947 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3948 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3949
3950 final int validKaInterval = 15;
3951 final int invalidKaInterval = 9;
3952
3953 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08003954 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
3955 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08003956
junyulai48eac1d42018-12-27 17:25:29 +08003957 LinkProperties lp = new LinkProperties();
3958 lp.setInterfaceName("wlan12");
3959 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3960 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3961 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3962 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3963
3964 Network notMyNet = new Network(61234);
3965 Network myNet = connectKeepaliveNetwork(lp);
3966
junyulai7c469172019-01-16 20:23:34 +08003967 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08003968
3969 // Attempt to start keepalives with invalid parameters and check for errors.
3970 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08003971 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3972 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3973 ka.start(validKaInterval);
3974 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
3975 }
junyulai48eac1d42018-12-27 17:25:29 +08003976
3977 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08003978 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3979 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
3980 ka.start(invalidKaInterval);
3981 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
3982 }
junyulai48eac1d42018-12-27 17:25:29 +08003983
3984 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08003985 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3986 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
3987 ka.start(validKaInterval);
3988 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3989 }
junyulai48eac1d42018-12-27 17:25:29 +08003990
3991 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08003992 try (SocketKeepalive ka = mCm.createSocketKeepalive(
3993 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
3994 ka.start(validKaInterval);
3995 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
3996 }
junyulai48eac1d42018-12-27 17:25:29 +08003997
3998 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08003999 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4000 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4001 ka.start(validKaInterval);
4002 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4003 }
junyulai48eac1d42018-12-27 17:25:29 +08004004
4005 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004006 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4007 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4008 ka.start(validKaInterval);
4009 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4010 }
junyulai48eac1d42018-12-27 17:25:29 +08004011
4012 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004013 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004014 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4015 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4016 ka.start(validKaInterval);
4017 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004018 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004019 ka.stop();
4020 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004021
junyulai0c666972019-03-04 22:45:36 +08004022 // Check that keepalive could be restarted.
4023 ka.start(validKaInterval);
4024 callback.expectStarted();
4025 ka.stop();
4026 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004027
junyulai0c666972019-03-04 22:45:36 +08004028 // Check that keepalive can be restarted without waiting for callback.
4029 ka.start(validKaInterval);
4030 callback.expectStarted();
4031 ka.stop();
4032 ka.start(validKaInterval);
4033 callback.expectStopped();
4034 callback.expectStarted();
4035 ka.stop();
4036 callback.expectStopped();
4037 }
junyulai7c469172019-01-16 20:23:34 +08004038
junyulai48eac1d42018-12-27 17:25:29 +08004039 // Check that deleting the IP address stops the keepalive.
4040 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004041 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4042 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4043 ka.start(validKaInterval);
4044 callback.expectStarted();
4045 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4046 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4047 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4048 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4049 mWiFiNetworkAgent.sendLinkProperties(lp);
4050 }
junyulai48eac1d42018-12-27 17:25:29 +08004051
4052 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004053 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4054 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4055 ka.start(validKaInterval);
4056 callback.expectStarted();
4057 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004058 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004059 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004060
junyulai0c666972019-03-04 22:45:36 +08004061 // ... and that stopping it after that has no adverse effects.
4062 waitForIdle();
4063 final Network myNetAlias = myNet;
4064 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4065 ka.stop();
4066 callback.assertNoCallback();
4067 }
junyulai48eac1d42018-12-27 17:25:29 +08004068
4069 // Reconnect.
4070 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004071 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08004072
4073 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4074 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004075 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004076 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4077 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4078 ka.start(validKaInterval);
4079 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004080
junyulai0c666972019-03-04 22:45:36 +08004081 // The second one gets slot 2.
4082 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004083 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4084 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004085 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4086 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4087 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4088 ka2.start(validKaInterval);
4089 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004090
junyulai0c666972019-03-04 22:45:36 +08004091 ka.stop();
4092 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004093
junyulai0c666972019-03-04 22:45:36 +08004094 ka2.stop();
4095 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004096
junyulai0c666972019-03-04 22:45:36 +08004097 testSocket.close();
4098 testSocket2.close();
4099 }
4100 }
junyulai06835112019-01-03 18:50:15 +08004101
junyulai15178152019-03-27 11:00:37 +08004102 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004103 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4104 // assertFalse(isUdpPortInUse(srcPort));
4105 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004106
junyulai06835112019-01-03 18:50:15 +08004107 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004108 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004109 mWiFiNetworkAgent = null;
4110 }
4111
4112 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004113 public void testTcpSocketKeepalives() throws Exception {
4114 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004115 }
4116
4117 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4118 final int srcPortV4 = 12345;
4119 final int srcPortV6 = 23456;
4120 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4121 final InetAddress myIPv6 = InetAddress.getByName("::1");
4122
4123 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004124
4125 final LinkProperties lp = new LinkProperties();
4126 lp.setInterfaceName("wlan12");
4127 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4128 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4129 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4130 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4131
4132 final Network notMyNet = new Network(61234);
4133 final Network myNet = connectKeepaliveNetwork(lp);
4134
4135 final Socket testSocketV4 = new Socket();
4136 final Socket testSocketV6 = new Socket();
4137
junyulai7c469172019-01-16 20:23:34 +08004138 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004139
4140 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4141 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004142 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4143 notMyNet, testSocketV4, executor, callback)) {
4144 ka.start(validKaInterval);
4145 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4146 }
Xiao Maa4637112019-02-07 15:03:57 +09004147
4148 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004149 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4150 myNet, testSocketV4, executor, callback)) {
4151 ka.start(validKaInterval);
4152 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4153 }
Xiao Maa4637112019-02-07 15:03:57 +09004154
4155 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004156 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4157 myNet, testSocketV6, executor, callback)) {
4158 ka.start(validKaInterval);
4159 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4160 }
Xiao Maa4637112019-02-07 15:03:57 +09004161
4162 // Bind the socket address
4163 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4164 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4165
4166 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004167 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4168 myNet, testSocketV4, executor, callback)) {
4169 ka.start(validKaInterval);
4170 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4171 }
Xiao Maa4637112019-02-07 15:03:57 +09004172
4173 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004174 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4175 myNet, testSocketV6, executor, callback)) {
4176 ka.start(validKaInterval);
4177 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4178 }
Xiao Maa4637112019-02-07 15:03:57 +09004179
4180 testSocketV4.close();
4181 testSocketV6.close();
4182
4183 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004184 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004185 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004186 }
4187
junyulai0c666972019-03-04 22:45:36 +08004188 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004189 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4190 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4191 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4192 final int validKaInterval = 15;
4193
4194 // Prepare the target network.
4195 LinkProperties lp = new LinkProperties();
4196 lp.setInterfaceName("wlan12");
4197 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4198 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4199 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004200 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4201 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004202
4203 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4204
4205 // Prepare the target file descriptor, keep only one instance.
4206 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004207 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4208 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004209 final ParcelFileDescriptor testPfd =
4210 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4211 testSocket.close();
4212 assertTrue(isUdpPortInUse(srcPort));
4213
4214 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4215 // block.
4216 try (SocketKeepalive ka = mCm.createNattKeepalive(
4217 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4218 ka.start(validKaInterval);
4219 callback.expectStarted();
4220 ka.stop();
4221 callback.expectStopped();
4222 }
4223
4224 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4225 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4226 // address.
4227 assertTrue(isUdpPortInUse(srcPort));
4228 final InetSocketAddress sa =
4229 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4230 assertEquals(anyIPv4, sa.getAddress());
4231
4232 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004233 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4234 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004235
4236 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004237 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004238 mWiFiNetworkAgent = null;
4239 }
4240
4241 private static boolean isUdpPortInUse(int port) {
4242 try (DatagramSocket ignored = new DatagramSocket(port)) {
4243 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004244 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004245 return true;
4246 }
4247 }
4248
junyulai48eac1d42018-12-27 17:25:29 +08004249 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004250 public void testGetCaptivePortalServerUrl() throws Exception {
4251 String url = mCm.getCaptivePortalServerUrl();
4252 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4253 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004254
4255 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004256 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004257 synchronized(sLock) {
4258 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004259 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004260 }
4261 return sNetwork != null;
4262 }
4263 }
4264
Chalard Jeane7b24752019-06-20 16:01:19 +09004265 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004266 synchronized(sLock) {
4267 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004268 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004269 }
4270 return sNetwork == null;
4271 }
4272 }
4273 }
4274
4275 private void assertPinnedToWifiWithCellDefault() {
4276 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4277 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4278 }
4279
4280 private void assertPinnedToWifiWithWifiDefault() {
4281 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4282 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4283 }
4284
4285 private void assertNotPinnedToWifi() {
4286 assertNull(mCm.getBoundNetworkForProcess());
4287 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4288 }
4289
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004290 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004291 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004292 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4293 .addTransportType(TRANSPORT_WIFI)
4294 .build();
4295 assertNull(mCm.getBoundNetworkForProcess());
4296
4297 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4298 assertNull(mCm.getBoundNetworkForProcess());
4299
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004300 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004301 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004302 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004303 mWiFiNetworkAgent.connect(false);
4304
4305 // When wi-fi connects, expect to be pinned.
4306 assertTrue(TestNetworkPinner.awaitPin(100));
4307 assertPinnedToWifiWithCellDefault();
4308
4309 // Disconnect and expect the pin to drop.
4310 mWiFiNetworkAgent.disconnect();
4311 assertTrue(TestNetworkPinner.awaitUnpin(100));
4312 assertNotPinnedToWifi();
4313
4314 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004315 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004316 mWiFiNetworkAgent.connect(false);
4317 assertFalse(TestNetworkPinner.awaitPin(100));
4318 assertNotPinnedToWifi();
4319
4320 // Pinning while connected causes the pin to take effect immediately.
4321 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4322 assertTrue(TestNetworkPinner.awaitPin(100));
4323 assertPinnedToWifiWithCellDefault();
4324
4325 // Explicitly unpin and expect to use the default network again.
4326 TestNetworkPinner.unpin();
4327 assertNotPinnedToWifi();
4328
4329 // Disconnect cell and wifi.
Chalard Jean407deb72019-11-19 16:14:30 +09004330 ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004331 mCellNetworkAgent.disconnect();
4332 mWiFiNetworkAgent.disconnect();
4333 waitFor(cv);
4334
4335 // Pinning takes effect even if the pinned network is the default when the pin is set...
4336 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004337 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004338 mWiFiNetworkAgent.connect(false);
4339 assertTrue(TestNetworkPinner.awaitPin(100));
4340 assertPinnedToWifiWithWifiDefault();
4341
4342 // ... and is maintained even when that network is no longer the default.
Chalard Jean407deb72019-11-19 16:14:30 +09004343 cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004344 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004345 mCellNetworkAgent.connect(true);
4346 waitFor(cv);
4347 assertPinnedToWifiWithCellDefault();
4348 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004349
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004350 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004351 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004352 // We can only have 99 callbacks, because MultipathPolicyTracker is
4353 // already one of them.
4354 final int MAX_REQUESTS = 99;
4355 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004356 final int INTENTS = 10;
4357 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4358
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004359 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004360 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004361
Hugo Benichi893a7622017-09-29 09:34:08 +09004362 int j = 0;
4363 while (j++ < CALLBACKS / 2) {
4364 NetworkCallback cb = new NetworkCallback();
4365 mCm.requestNetwork(networkRequest, cb);
4366 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004367 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004368 while (j++ < CALLBACKS) {
4369 NetworkCallback cb = new NetworkCallback();
4370 mCm.registerNetworkCallback(networkRequest, cb);
4371 registered.add(cb);
4372 }
4373 j = 0;
4374 while (j++ < INTENTS / 2) {
4375 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4376 mCm.requestNetwork(networkRequest, pi);
4377 registered.add(pi);
4378 }
4379 while (j++ < INTENTS) {
4380 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4381 mCm.registerNetworkCallback(networkRequest, pi);
4382 registered.add(pi);
4383 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004384
Hugo Benichi893a7622017-09-29 09:34:08 +09004385 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004386 assertThrows(TooManyRequestsException.class, () ->
4387 mCm.requestNetwork(networkRequest, new NetworkCallback())
4388 );
4389 assertThrows(TooManyRequestsException.class, () ->
4390 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4391 );
4392 assertThrows(TooManyRequestsException.class, () ->
4393 mCm.requestNetwork(networkRequest,
4394 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4395 );
4396 assertThrows(TooManyRequestsException.class, () ->
4397 mCm.registerNetworkCallback(networkRequest,
4398 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4399 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004400
Hugo Benichi893a7622017-09-29 09:34:08 +09004401 for (Object o : registered) {
4402 if (o instanceof NetworkCallback) {
4403 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004404 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004405 if (o instanceof PendingIntent) {
4406 mCm.unregisterNetworkCallback((PendingIntent)o);
4407 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004408 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004409 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004410
4411 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4412 for (int i = 0; i < MAX_REQUESTS; i++) {
4413 NetworkCallback networkCallback = new NetworkCallback();
4414 mCm.requestNetwork(networkRequest, networkCallback);
4415 mCm.unregisterNetworkCallback(networkCallback);
4416 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004417 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004418
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004419 for (int i = 0; i < MAX_REQUESTS; i++) {
4420 NetworkCallback networkCallback = new NetworkCallback();
4421 mCm.registerNetworkCallback(networkRequest, networkCallback);
4422 mCm.unregisterNetworkCallback(networkCallback);
4423 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004424 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004425
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004426 for (int i = 0; i < MAX_REQUESTS; i++) {
4427 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004428 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004429 mCm.requestNetwork(networkRequest, pendingIntent);
4430 mCm.unregisterNetworkCallback(pendingIntent);
4431 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004432 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004433
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004434 for (int i = 0; i < MAX_REQUESTS; i++) {
4435 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004436 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004437 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4438 mCm.unregisterNetworkCallback(pendingIntent);
4439 }
4440 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004441
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004442 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004443 public void testNetworkInfoOfTypeNone() throws Exception {
Chalard Jean407deb72019-11-19 16:14:30 +09004444 ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004445
4446 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004447 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004448 assertNull(mCm.getActiveNetworkInfo());
4449
4450 Network[] allNetworks = mCm.getAllNetworks();
4451 assertLength(1, allNetworks);
4452 Network network = allNetworks[0];
4453 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4454 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4455
4456 final NetworkRequest request =
4457 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4458 final TestNetworkCallback callback = new TestNetworkCallback();
4459 mCm.registerNetworkCallback(request, callback);
4460
Hugo Benichic1014502017-07-19 10:10:52 +09004461 // Bring up wifi aware network.
lucaslin783f2212019-10-22 18:27:33 +08004462 wifiAware.connect(false, false, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004463 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004464
4465 assertNull(mCm.getActiveNetworkInfo());
4466 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004467 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004468 // of this test. Fix it and uncomment the assert below.
4469 //assertEmpty(mCm.getAllNetworkInfo());
4470
Hugo Benichic1014502017-07-19 10:10:52 +09004471 // Disconnect wifi aware network.
4472 wifiAware.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09004473 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004474 mCm.unregisterNetworkCallback(callback);
4475
4476 verifyNoNetwork();
4477 if (broadcastCV.block(10)) {
4478 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4479 }
4480 }
4481
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004482 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004483 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4484 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4485 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4486 assertNull(mCm.getNetworkForType(TYPE_NONE));
4487 assertNull(mCm.getLinkProperties(TYPE_NONE));
4488 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4489
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004490 assertThrows(IllegalArgumentException.class,
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004491 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004492
4493 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004494 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4495 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004496 // TODO: let test context have configuration application target sdk version
4497 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004498 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4499 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4500 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004501 }
4502
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004503 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004504 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004505 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4506 .addTransportType(TRANSPORT_WIFI).build();
4507 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4508 mCm.registerNetworkCallback(networkRequest, networkCallback);
4509
4510 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004511 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004512 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4513 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4514 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4515 lp.addLinkAddress(myIpv4Address);
4516 lp.addRoute(myIpv4DefaultRoute);
4517
4518 // Verify direct routes are added when network agent is first registered in
4519 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004520 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004521 networkAgent.connect(true);
Chalard Jean059c4262019-09-30 17:51:12 +09004522 networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
4523 networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
4524 CallbackEntry.LinkPropertiesChanged cbi =
4525 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004526 networkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004527 networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004528 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4529 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004530 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004531 Arrays.asList(myIpv4DefaultRoute));
4532 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4533 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4534
4535 // Verify direct routes are added during subsequent link properties updates.
4536 LinkProperties newLp = new LinkProperties(lp);
4537 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4538 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4539 newLp.addLinkAddress(myIpv6Address1);
4540 newLp.addLinkAddress(myIpv6Address2);
4541 networkAgent.sendLinkProperties(newLp);
Chalard Jean059c4262019-09-30 17:51:12 +09004542 cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004543 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004544 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004545 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4546 Arrays.asList(myIpv4DefaultRoute));
4547 mCm.unregisterNetworkCallback(networkCallback);
4548 }
4549
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004550 @Test
4551 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004552 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4553 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004554
Varun Anandd33cbc62019-02-07 14:13:13 -08004555 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4556 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4557
4558 LinkProperties cellLp = new LinkProperties();
4559 cellLp.setInterfaceName(MOBILE_IFNAME);
4560 LinkProperties wifiLp = new LinkProperties();
4561 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004562
4563 // Simple connection should have updated ifaces
4564 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004565 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004566 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004567 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004568 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4569 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004570 reset(mStatsService);
4571
4572 // Default network switch should update ifaces.
4573 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004574 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004575 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004576 assertEquals(wifiLp, mService.getActiveLinkProperties());
4577 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004578 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4579 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004580 reset(mStatsService);
4581
4582 // Disconnect should update ifaces.
4583 mWiFiNetworkAgent.disconnect();
4584 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004585 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004586 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4587 eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004588 reset(mStatsService);
4589
4590 // Metered change should update ifaces
4591 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4592 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004593 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004594 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4595 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004596 reset(mStatsService);
4597
4598 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4599 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004600 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004601 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4602 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004603 reset(mStatsService);
4604
4605 // Captive portal change shouldn't update ifaces
4606 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4607 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004608 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004609 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4610 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004611 reset(mStatsService);
4612
4613 // Roaming change should update ifaces
4614 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4615 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004616 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004617 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4618 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004619 reset(mStatsService);
4620 }
4621
Erik Klinee89953b2018-01-11 16:11:10 +09004622 @Test
4623 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004624 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004625
4626 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004627 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004628
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004629 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09004630 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004631 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004632 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004633
4634 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004635 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004636 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4637 // "is-reachable" testing in order to not program netd with unreachable
4638 // nameservers that it might try repeated to validate.
4639 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004640 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4641 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004642 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004643 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4644 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004645 mCellNetworkAgent.sendLinkProperties(cellLp);
4646 mCellNetworkAgent.connect(false);
4647 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004648
4649 verify(mMockDnsResolver, times(1)).createNetworkCache(
4650 eq(mCellNetworkAgent.getNetwork().netId));
4651 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004652 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004653 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004654
4655 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4656 mCellNetworkAgent.sendLinkProperties(cellLp);
4657 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004658 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004659 mResolverParamsParcelCaptor.capture());
4660 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4661 assertEquals(1, resolvrParams.servers.length);
4662 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004663 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004664 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004665 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004666
4667 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4668 mCellNetworkAgent.sendLinkProperties(cellLp);
4669 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004670 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004671 mResolverParamsParcelCaptor.capture());
4672 resolvrParams = mResolverParamsParcelCaptor.getValue();
4673 assertEquals(2, resolvrParams.servers.length);
4674 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004675 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004676 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004677 assertEquals(2, resolvrParams.tlsServers.length);
4678 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004679 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004680 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004681
4682 final String TLS_SPECIFIER = "tls.example.com";
4683 final String TLS_SERVER6 = "2001:db8:53::53";
4684 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4685 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004686 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4687 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4688
Erik Kline117e7f32018-03-04 21:01:01 +09004689 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004690 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004691 mResolverParamsParcelCaptor.capture());
4692 resolvrParams = mResolverParamsParcelCaptor.getValue();
4693 assertEquals(2, resolvrParams.servers.length);
4694 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004695 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004696 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004697 }
4698
Erik Kline79c6d052018-03-21 07:18:33 -07004699 @Test
lucaslin783f2212019-10-22 18:27:33 +08004700 public void testPrivateDnsNotification() throws Exception {
4701 NetworkRequest request = new NetworkRequest.Builder()
4702 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4703 .build();
4704 TestNetworkCallback callback = new TestNetworkCallback();
4705 mCm.registerNetworkCallback(request, callback);
4706 // Bring up wifi.
4707 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4708 mWiFiNetworkAgent.connect(false);
4709 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4710 // Private DNS resolution failed, checking if the notification will be shown or not.
4711 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4712 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4713 waitForIdle();
4714 // If network validation failed, NetworkMonitor will re-evaluate the network.
4715 // ConnectivityService should filter the redundant notification. This part is trying to
4716 // simulate that situation and check if ConnectivityService could filter that case.
4717 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4718 waitForIdle();
4719 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
4720 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4721 // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
4722 // shown.
4723 mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
4724 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4725 waitForIdle();
4726 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
4727 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
4728 // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
4729 // shown again.
4730 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4731 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4732 waitForIdle();
4733 verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
4734 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4735 }
4736
4737 @Test
Erik Kline79c6d052018-03-21 07:18:33 -07004738 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004739 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004740 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004741
4742 // The default on Android is opportunistic mode ("Automatic").
4743 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4744
dalyk1fcb7392018-03-05 12:42:22 -05004745 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4746 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4747 .addTransportType(TRANSPORT_CELLULAR).build();
4748 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4749
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004750 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07004751 waitForIdle();
4752 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004753 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004754 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004755
4756 final LinkProperties cellLp = new LinkProperties();
4757 cellLp.setInterfaceName(MOBILE_IFNAME);
4758 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4759 // "is-reachable" testing in order to not program netd with unreachable
4760 // nameservers that it might try repeated to validate.
4761 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4762 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4763 MOBILE_IFNAME));
4764 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4765 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4766 MOBILE_IFNAME));
4767 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4768 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4769
4770 mCellNetworkAgent.sendLinkProperties(cellLp);
4771 mCellNetworkAgent.connect(false);
4772 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004773 verify(mMockDnsResolver, times(1)).createNetworkCache(
4774 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08004775 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004776 mResolverParamsParcelCaptor.capture());
4777 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4778 assertEquals(2, resolvrParams.tlsServers.length);
4779 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004780 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07004781 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004782 assertEquals(2, resolvrParams.tlsServers.length);
4783 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004784 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004785 reset(mMockDnsResolver);
Chalard Jean059c4262019-09-30 17:51:12 +09004786 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
4787 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004788 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004789 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4790 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4791 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004792 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004793 assertFalse(cbi.getLp().isPrivateDnsActive());
4794 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004795
4796 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004797 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004798 mResolverParamsParcelCaptor.capture());
4799 resolvrParams = mResolverParamsParcelCaptor.getValue();
4800 assertEquals(2, resolvrParams.servers.length);
4801 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004802 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004803 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004804 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004805
4806 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004807 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004808 mResolverParamsParcelCaptor.capture());
4809 resolvrParams = mResolverParamsParcelCaptor.getValue();
4810 assertEquals(2, resolvrParams.servers.length);
4811 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004812 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08004813 assertEquals(2, resolvrParams.tlsServers.length);
4814 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004815 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004816 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004817 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004818
dalyk1fcb7392018-03-05 12:42:22 -05004819 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4820 // Can't test dns configuration for strict mode without properly mocking
4821 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean059c4262019-09-30 17:51:12 +09004822 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004823 mCellNetworkAgent);
4824 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004825 assertTrue(cbi.getLp().isPrivateDnsActive());
4826 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004827 }
4828
4829 @Test
4830 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4831 // The default on Android is opportunistic mode ("Automatic").
4832 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4833
4834 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4835 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4836 .addTransportType(TRANSPORT_CELLULAR).build();
4837 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4838
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004839 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05004840 waitForIdle();
4841 LinkProperties lp = new LinkProperties();
4842 mCellNetworkAgent.sendLinkProperties(lp);
4843 mCellNetworkAgent.connect(false);
4844 waitForIdle();
Chalard Jean059c4262019-09-30 17:51:12 +09004845 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
4846 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004847 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004848 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4849 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4850 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004851 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004852 assertFalse(cbi.getLp().isPrivateDnsActive());
4853 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004854 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004855 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004856
4857 // Send a validation event for a server that is not part of the current
4858 // resolver config. The validation event should be ignored.
4859 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4860 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4861 cellNetworkCallback.assertNoCallback();
4862
4863 // Add a dns server to the LinkProperties.
4864 LinkProperties lp2 = new LinkProperties(lp);
4865 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4866 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean059c4262019-09-30 17:51:12 +09004867 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004868 mCellNetworkAgent);
4869 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004870 assertFalse(cbi.getLp().isPrivateDnsActive());
4871 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004872 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004873 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004874
4875 // Send a validation event containing a hostname that is not part of
4876 // the current resolver config. The validation event should be ignored.
4877 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4878 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4879 cellNetworkCallback.assertNoCallback();
4880
4881 // Send a validation event where validation failed.
4882 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4883 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4884 cellNetworkCallback.assertNoCallback();
4885
4886 // Send a validation event where validation succeeded for a server in
4887 // the current resolver config. A LinkProperties callback with updated
4888 // private dns fields should be sent.
4889 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4890 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean059c4262019-09-30 17:51:12 +09004891 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004892 mCellNetworkAgent);
4893 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004894 assertTrue(cbi.getLp().isPrivateDnsActive());
4895 assertNull(cbi.getLp().getPrivateDnsServerName());
4896 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004897
4898 // The private dns fields in LinkProperties should be preserved when
4899 // the network agent sends unrelated changes.
4900 LinkProperties lp3 = new LinkProperties(lp2);
4901 lp3.setMtu(1300);
4902 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean059c4262019-09-30 17:51:12 +09004903 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004904 mCellNetworkAgent);
4905 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004906 assertTrue(cbi.getLp().isPrivateDnsActive());
4907 assertNull(cbi.getLp().getPrivateDnsServerName());
4908 checkDnsServers(cbi.getLp(), dnsServers);
4909 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05004910
4911 // Removing the only validated server should affect the private dns
4912 // fields in LinkProperties.
4913 LinkProperties lp4 = new LinkProperties(lp3);
4914 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
4915 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean059c4262019-09-30 17:51:12 +09004916 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004917 mCellNetworkAgent);
4918 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004919 assertFalse(cbi.getLp().isPrivateDnsActive());
4920 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004921 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004922 checkDnsServers(cbi.getLp(), dnsServers);
4923 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07004924 }
4925
Rubin Xu1bb5c082017-09-05 18:40:49 +01004926 private void checkDirectlyConnectedRoutes(Object callbackObj,
4927 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
4928 assertTrue(callbackObj instanceof LinkProperties);
4929 LinkProperties lp = (LinkProperties) callbackObj;
4930
4931 Set<RouteInfo> expectedRoutes = new ArraySet<>();
4932 expectedRoutes.addAll(otherRoutes);
4933 for (LinkAddress address : linkAddresses) {
4934 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
4935 // Duplicates in linkAddresses are considered failures
4936 assertTrue(expectedRoutes.add(localRoute));
4937 }
4938 List<RouteInfo> observedRoutes = lp.getRoutes();
4939 assertEquals(expectedRoutes.size(), observedRoutes.size());
4940 assertTrue(observedRoutes.containsAll(expectedRoutes));
4941 }
4942
dalyk1fcb7392018-03-05 12:42:22 -05004943 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
4944 assertTrue(callbackObj instanceof LinkProperties);
4945 LinkProperties lp = (LinkProperties) callbackObj;
4946 assertEquals(dnsServers.size(), lp.getDnsServers().size());
4947 assertTrue(lp.getDnsServers().containsAll(dnsServers));
4948 }
4949
Chalard Jean0b214af2018-01-12 17:22:49 +09004950 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004951 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09004952 final int uid = Process.myUid();
4953
4954 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004955 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004956 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
4957 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004958 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09004959 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
4960 final NetworkRequest genericRequest = new NetworkRequest.Builder()
4961 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09004962 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
4963 .addTransportType(TRANSPORT_WIFI).build();
4964 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09004965 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09004966 .addTransportType(TRANSPORT_VPN).build();
4967 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09004968 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09004969 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
4970 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004971 mCm.registerDefaultNetworkCallback(defaultCallback);
4972 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09004973
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004974 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09004975 mWiFiNetworkAgent.connect(false);
4976
4977 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09004978 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004979 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004980 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09004981 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09004982 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09004983
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004984 final TestNetworkAgentWrapper
4985 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean0b214af2018-01-12 17:22:49 +09004986 final ArraySet<UidRange> ranges = new ArraySet<>();
4987 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004988 mMockVpn.setNetworkAgent(vpnNetworkAgent);
4989 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004990 // VPN networks do not satisfy the default request and are automatically validated
4991 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004992 assertFalse(NetworkMonitorUtils.isValidationRequired(
4993 vpnNetworkAgent.getNetworkCapabilities()));
lucaslin783f2212019-10-22 18:27:33 +08004994 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004995
Chalard Jean0b214af2018-01-12 17:22:49 +09004996 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09004997 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08004998 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09004999
5000 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005001 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005002 wifiNetworkCallback.assertNoCallback();
5003 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005004 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5005 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005006
Chalard Jean059c4262019-09-30 17:51:12 +09005007 genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005008 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005009 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
Chalard Jean059c4262019-09-30 17:51:12 +09005010 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005011 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005012
5013 ranges.clear();
5014 vpnNetworkAgent.setUids(ranges);
5015
Chalard Jean059c4262019-09-30 17:51:12 +09005016 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005017 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005018 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005019 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005020
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005021 // TODO : The default network callback should actually get a LOST call here (also see the
5022 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5023 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5024 // can't currently update their UIDs without disconnecting, so this does not matter too
5025 // much, but that is the reason the test here has to check for an update to the
5026 // capabilities instead of the expected LOST then AVAILABLE.
Chalard Jean059c4262019-09-30 17:51:12 +09005027 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005028
Chalard Jean0b214af2018-01-12 17:22:49 +09005029 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005030 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005031 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005032
5033 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005034 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005035 wifiNetworkCallback.assertNoCallback();
5036 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005037 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5038 // happen outside of the test, ConnectivityService does not rematch callbacks.
Chalard Jean059c4262019-09-30 17:51:12 +09005039 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005040
5041 mWiFiNetworkAgent.disconnect();
5042
Chalard Jean059c4262019-09-30 17:51:12 +09005043 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5044 genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5045 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005046 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005047 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005048
5049 vpnNetworkAgent.disconnect();
5050
Chalard Jean059c4262019-09-30 17:51:12 +09005051 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005052 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005053 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005054 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5055 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005056 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005057
5058 mCm.unregisterNetworkCallback(genericNetworkCallback);
5059 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5060 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005061 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005062 }
Chalard Jean26400492018-04-18 20:18:38 +09005063
5064 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005065 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09005066 final int uid = Process.myUid();
5067
5068 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5069 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005070
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005071 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09005072 mWiFiNetworkAgent.connect(true);
5073
5074 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5075 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5076
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005077 TestNetworkAgentWrapper
5078 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09005079 final ArraySet<UidRange> ranges = new ArraySet<>();
5080 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005081 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5082 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005083 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5084 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005085 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005086
5087 defaultCallback.assertNoCallback();
5088 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5089
5090 vpnNetworkAgent.disconnect();
5091 defaultCallback.assertNoCallback();
5092
Varun Anand4fa80e82019-02-06 10:13:38 -08005093 mCm.unregisterNetworkCallback(defaultCallback);
5094 }
5095
5096 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005097 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005098 final int uid = Process.myUid();
5099
5100 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5101 mCm.registerDefaultNetworkCallback(defaultCallback);
5102
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005103 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005104 mWiFiNetworkAgent.connect(true);
5105
5106 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5107 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5108
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005109 TestNetworkAgentWrapper
5110 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005111 final ArraySet<UidRange> ranges = new ArraySet<>();
5112 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005113 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5114 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005115 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
5116 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005117 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005118
Chalard Jean26400492018-04-18 20:18:38 +09005119 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5120 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5121
5122 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005123 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean26400492018-04-18 20:18:38 +09005124 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5125
Chalard Jean26400492018-04-18 20:18:38 +09005126 mCm.unregisterNetworkCallback(defaultCallback);
5127 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005128
5129 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005130 public void testVpnUnvalidated() throws Exception {
5131 final TestNetworkCallback callback = new TestNetworkCallback();
5132 mCm.registerDefaultNetworkCallback(callback);
5133
5134 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005135 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005136 mEthernetNetworkAgent.connect(true);
5137 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5138 callback.assertNoCallback();
5139
5140 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5141 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005142 final TestNetworkAgentWrapper
5143 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005144 final ArraySet<UidRange> ranges = new ArraySet<>();
5145 ranges.add(new UidRange(uid, uid));
5146 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5147 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005148 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
5149 false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005150 mMockVpn.connect();
5151
5152 // Even though the VPN is unvalidated, it becomes the default network for our app.
5153 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5154 // TODO: this looks like a spurious callback.
Chalard Jean059c4262019-09-30 17:51:12 +09005155 callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005156 callback.assertNoCallback();
5157
5158 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5159 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5160 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5161
5162 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5163 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5164 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5165
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005166 assertFalse(NetworkMonitorUtils.isValidationRequired(
5167 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005168 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005169 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005170
5171 // Pretend that the VPN network validates.
lucaslin783f2212019-10-22 18:27:33 +08005172 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005173 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5174 // Expect to see the validated capability, but no other changes, because the VPN is already
5175 // the default network for the app.
5176 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5177 callback.assertNoCallback();
5178
5179 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005180 callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005181 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5182 }
5183
5184 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005185 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005186 final int uid = Process.myUid();
5187
5188 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5189 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5190 .removeCapability(NET_CAPABILITY_NOT_VPN)
5191 .addTransportType(TRANSPORT_VPN)
5192 .build();
5193 NetworkCapabilities nc;
5194 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5195 vpnNetworkCallback.assertNoCallback();
5196
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005197 final TestNetworkAgentWrapper
5198 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005199 final ArraySet<UidRange> ranges = new ArraySet<>();
5200 ranges.add(new UidRange(uid, uid));
5201 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5202 mMockVpn.connect();
5203 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005204 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5205 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005206
5207 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5208 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5209 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5210 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5211 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5212 // For safety reasons a VPN without underlying networks is considered metered.
5213 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5214
5215 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005216 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005217 mCellNetworkAgent.connect(true);
5218
5219 mService.setUnderlyingNetworksForVpn(
5220 new Network[] { mCellNetworkAgent.getNetwork() });
5221
Chalard Jean6f4216f2019-06-05 01:40:32 +09005222 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5223 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005224 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005225 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005226
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005227 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005228 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5229 mWiFiNetworkAgent.connect(true);
5230
5231 mService.setUnderlyingNetworksForVpn(
5232 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5233
Chalard Jean6f4216f2019-06-05 01:40:32 +09005234 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5235 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005236 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005237 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005238
5239 // Don't disconnect, but note the VPN is not using wifi any more.
5240 mService.setUnderlyingNetworksForVpn(
5241 new Network[] { mCellNetworkAgent.getNetwork() });
5242
Chalard Jean6f4216f2019-06-05 01:40:32 +09005243 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5244 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005245 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005246 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005247
5248 // Use Wifi but not cell. Note the VPN is now unmetered.
5249 mService.setUnderlyingNetworksForVpn(
5250 new Network[] { mWiFiNetworkAgent.getNetwork() });
5251
Chalard Jean6f4216f2019-06-05 01:40:32 +09005252 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5253 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005254 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005255 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005256
5257 // Use both again.
5258 mService.setUnderlyingNetworksForVpn(
5259 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5260
Chalard Jean6f4216f2019-06-05 01:40:32 +09005261 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5262 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005263 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005264 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005265
Chalard Jean6b65ec72018-05-18 22:02:56 +09005266 // Disconnect cell. Receive update without even removing the dead network from the
5267 // underlying networks – it's dead anyway. Not metered any more.
5268 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005269 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5270 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005271 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005272 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005273
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005274 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005275 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005276 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5277 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005278 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005279 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005280
5281 mMockVpn.disconnect();
5282 }
junyulai4a192e22018-06-13 15:00:37 +08005283
Mike Yuf9729752018-08-17 15:22:05 +08005284 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005285 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005286 final int uid = Process.myUid();
5287
5288 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5289 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5290 .removeCapability(NET_CAPABILITY_NOT_VPN)
5291 .addTransportType(TRANSPORT_VPN)
5292 .build();
5293 NetworkCapabilities nc;
5294 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5295 vpnNetworkCallback.assertNoCallback();
5296
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005297 final TestNetworkAgentWrapper
5298 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005299 final ArraySet<UidRange> ranges = new ArraySet<>();
5300 ranges.add(new UidRange(uid, uid));
5301 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5302 mMockVpn.connect();
5303 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005304 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5305 false /* isStrictMode */);
Varun Anand4fa80e82019-02-06 10:13:38 -08005306
5307 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5308 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5309 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5310 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5311 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5312 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5313 // In case of no default network, VPN is considered metered.
5314 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5315
5316 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005317 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005318 mCellNetworkAgent.connect(true);
5319
Chalard Jean6f4216f2019-06-05 01:40:32 +09005320 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5321 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005322 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005323 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005324
5325 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005326 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005327 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5328 mWiFiNetworkAgent.connect(true);
5329
Chalard Jean6f4216f2019-06-05 01:40:32 +09005330 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5331 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005332 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005333 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005334
5335 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5336 // the capabilities.
5337 mCellNetworkAgent.disconnect();
5338
5339 // Disconnect wifi too. Now we have no default network.
5340 mWiFiNetworkAgent.disconnect();
5341
Chalard Jean6f4216f2019-06-05 01:40:32 +09005342 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5343 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005344 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005345 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005346
5347 mMockVpn.disconnect();
5348 }
5349
5350 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005351 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005352 // Returns true by default when no network is available.
5353 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005354 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005355 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5356 mWiFiNetworkAgent.connect(true);
5357 waitForIdle();
5358
5359 assertFalse(mCm.isActiveNetworkMetered());
5360 }
5361
5362 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005363 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005364 // Returns true by default when no network is available.
5365 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005366 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005367 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5368 mCellNetworkAgent.connect(true);
5369 waitForIdle();
5370
5371 assertTrue(mCm.isActiveNetworkMetered());
5372 }
5373
5374 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005375 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005376 // Returns true by default when no network is available.
5377 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005378 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005379 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5380 mCellNetworkAgent.connect(true);
5381 waitForIdle();
5382 assertTrue(mCm.isActiveNetworkMetered());
5383
5384 // Connect VPN network. By default it is using current default network (Cell).
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005385 TestNetworkAgentWrapper
5386 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005387 final ArraySet<UidRange> ranges = new ArraySet<>();
5388 final int uid = Process.myUid();
5389 ranges.add(new UidRange(uid, uid));
5390 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5391 mMockVpn.setUids(ranges);
5392 vpnNetworkAgent.connect(true);
5393 mMockVpn.connect();
5394 waitForIdle();
5395 // Ensure VPN is now the active network.
5396 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5397
5398 // Expect VPN to be metered.
5399 assertTrue(mCm.isActiveNetworkMetered());
5400
5401 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005402 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005403 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5404 mWiFiNetworkAgent.connect(true);
5405 waitForIdle();
5406 // VPN should still be the active network.
5407 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5408
5409 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5410 assertFalse(mCm.isActiveNetworkMetered());
5411
5412 // Disconnecting Cell should not affect VPN's meteredness.
5413 mCellNetworkAgent.disconnect();
5414 waitForIdle();
5415
5416 assertFalse(mCm.isActiveNetworkMetered());
5417
5418 // Disconnect WiFi; Now there is no platform default network.
5419 mWiFiNetworkAgent.disconnect();
5420 waitForIdle();
5421
5422 // VPN without any underlying networks is treated as metered.
5423 assertTrue(mCm.isActiveNetworkMetered());
5424
5425 vpnNetworkAgent.disconnect();
5426 mMockVpn.disconnect();
5427 }
5428
5429 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005430 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005431 // Returns true by default when no network is available.
5432 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005433 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005434 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5435 mCellNetworkAgent.connect(true);
5436 waitForIdle();
5437 assertTrue(mCm.isActiveNetworkMetered());
5438
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005439 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005440 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5441 mWiFiNetworkAgent.connect(true);
5442 waitForIdle();
5443 assertFalse(mCm.isActiveNetworkMetered());
5444
5445 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005446 TestNetworkAgentWrapper
5447 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005448 final ArraySet<UidRange> ranges = new ArraySet<>();
5449 final int uid = Process.myUid();
5450 ranges.add(new UidRange(uid, uid));
5451 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5452 mMockVpn.setUids(ranges);
5453 vpnNetworkAgent.connect(true);
5454 mMockVpn.connect();
5455 waitForIdle();
5456 // Ensure VPN is now the active network.
5457 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5458 // VPN is using Cell
5459 mService.setUnderlyingNetworksForVpn(
5460 new Network[] { mCellNetworkAgent.getNetwork() });
5461 waitForIdle();
5462
5463 // Expect VPN to be metered.
5464 assertTrue(mCm.isActiveNetworkMetered());
5465
5466 // VPN is now using WiFi
5467 mService.setUnderlyingNetworksForVpn(
5468 new Network[] { mWiFiNetworkAgent.getNetwork() });
5469 waitForIdle();
5470
5471 // Expect VPN to be unmetered
5472 assertFalse(mCm.isActiveNetworkMetered());
5473
5474 // VPN is using Cell | WiFi.
5475 mService.setUnderlyingNetworksForVpn(
5476 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5477 waitForIdle();
5478
5479 // Expect VPN to be metered.
5480 assertTrue(mCm.isActiveNetworkMetered());
5481
5482 // VPN is using WiFi | Cell.
5483 mService.setUnderlyingNetworksForVpn(
5484 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5485 waitForIdle();
5486
5487 // Order should not matter and VPN should still be metered.
5488 assertTrue(mCm.isActiveNetworkMetered());
5489
5490 // VPN is not using any underlying networks.
5491 mService.setUnderlyingNetworksForVpn(new Network[0]);
5492 waitForIdle();
5493
5494 // VPN without underlying networks is treated as metered.
5495 assertTrue(mCm.isActiveNetworkMetered());
5496
5497 vpnNetworkAgent.disconnect();
5498 mMockVpn.disconnect();
5499 }
5500
5501 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005502 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005503 // Returns true by default when no network is available.
5504 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005505 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005506 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5507 mWiFiNetworkAgent.connect(true);
5508 waitForIdle();
5509 assertFalse(mCm.isActiveNetworkMetered());
5510
5511 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005512 TestNetworkAgentWrapper
5513 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005514 final ArraySet<UidRange> ranges = new ArraySet<>();
5515 final int uid = Process.myUid();
5516 ranges.add(new UidRange(uid, uid));
5517 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5518 mMockVpn.setUids(ranges);
5519 vpnNetworkAgent.connect(true);
5520 mMockVpn.connectAsAlwaysMetered();
5521 waitForIdle();
5522 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5523
5524 // VPN is tracking current platform default (WiFi).
5525 mService.setUnderlyingNetworksForVpn(null);
5526 waitForIdle();
5527
5528 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5529 assertTrue(mCm.isActiveNetworkMetered());
5530
5531 // VPN explicitly declares WiFi as its underlying network.
5532 mService.setUnderlyingNetworksForVpn(
5533 new Network[] { mWiFiNetworkAgent.getNetwork() });
5534 waitForIdle();
5535
5536 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5537 assertTrue(mCm.isActiveNetworkMetered());
5538
5539 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5540 // anyways suppose to be metered.
5541 mWiFiNetworkAgent.disconnect();
5542 waitForIdle();
5543
5544 assertTrue(mCm.isActiveNetworkMetered());
5545
5546 vpnNetworkAgent.disconnect();
5547 }
5548
5549 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005550 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005551 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5552 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5553 .addTransportType(TRANSPORT_CELLULAR)
5554 .build();
5555 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5556
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005557 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005558 mCellNetworkAgent.connect(true);
5559 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5560
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005561 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08005562 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5563
5564 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005565 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005566 cellNetworkCallback.assertNoCallback();
5567
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005568 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005569 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5570
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005571 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005572 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5573
5574 // Restrict the network based on UID rule and NOT_METERED capability change.
5575 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5576 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5577 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5578 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5579 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5580 mCellNetworkAgent);
5581 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005582 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005583 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5584
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005585 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005586 cellNetworkCallback.assertNoCallback();
5587
5588 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005589 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005590 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005591 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005592 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005593 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005594 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5595 cellNetworkCallback.assertNoCallback();
5596
5597 mCm.unregisterNetworkCallback(cellNetworkCallback);
5598 }
5599
5600 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005601 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005602 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5603 mCm.registerDefaultNetworkCallback(defaultCallback);
5604
5605 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005606 setUidRulesChanged(RULE_REJECT_ALL);
5607 setUidRulesChanged(RULE_NONE);
5608 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005609 defaultCallback.assertNoCallback();
5610
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005611 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005612 mCellNetworkAgent.connect(true);
5613 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5614 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5615
5616 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005617 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08005618 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5619 mWiFiNetworkAgent.connect(true);
5620 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5621
5622 // Switch to METERED network. Restrict the use of the network.
5623 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005624 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005625 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5626
5627 // Network becomes NOT_METERED.
5628 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5629 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5630 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5631
5632 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005633 setRestrictBackgroundChanged(true);
5634 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005635 defaultCallback.assertNoCallback();
5636
5637 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005638 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005639 defaultCallback.assertNoCallback();
5640
5641 mCm.unregisterNetworkCallback(defaultCallback);
5642 }
5643
Chalard Jean587758b2019-11-29 16:41:50 +09005644 @Test
5645 public final void testBatteryStatsNetworkType() throws Exception {
5646 final LinkProperties cellLp = new LinkProperties();
5647 cellLp.setInterfaceName("cell0");
5648 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5649 mCellNetworkAgent.connect(true);
5650 waitForIdle();
5651 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5652 TYPE_MOBILE);
5653 reset(mBatteryStatsService);
5654
5655 final LinkProperties wifiLp = new LinkProperties();
5656 wifiLp.setInterfaceName("wifi0");
5657 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
5658 mWiFiNetworkAgent.connect(true);
5659 waitForIdle();
5660 verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(),
5661 TYPE_WIFI);
5662 reset(mBatteryStatsService);
5663
Chalard Jean587758b2019-11-29 16:41:50 +09005664 mCellNetworkAgent.disconnect();
5665
5666 cellLp.setInterfaceName("wifi0");
5667 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5668 mCellNetworkAgent.connect(true);
5669 waitForIdle();
5670 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5671 TYPE_MOBILE);
5672 }
5673
junyulai4a192e22018-06-13 15:00:37 +08005674 /**
5675 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5676 */
5677 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5678 InterfaceConfiguration cfg = new InterfaceConfiguration();
5679 cfg.setHardwareAddress("11:22:33:44:55:66");
5680 cfg.setLinkAddress(la);
5681 return cfg;
5682 }
5683
5684 /**
5685 * Make expected stack link properties, copied from Nat464Xlat.
5686 */
5687 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5688 LinkAddress clatAddress = la;
5689 LinkProperties stacked = new LinkProperties();
5690 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5691 RouteInfo ipv4Default = new RouteInfo(
5692 new LinkAddress(Inet4Address.ANY, 0),
5693 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5694 stacked.addRoute(ipv4Default);
5695 stacked.addLinkAddress(clatAddress);
5696 return stacked;
5697 }
5698
5699 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005700 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08005701 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5702 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005703 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5704 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5705
junyulai4a192e22018-06-13 15:00:37 +08005706 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5707 .addTransportType(TRANSPORT_CELLULAR)
5708 .addCapability(NET_CAPABILITY_INTERNET)
5709 .build();
5710 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5711 mCm.registerNetworkCallback(networkRequest, networkCallback);
5712
Lorenzo Colittid593e292019-02-19 13:21:56 +09005713 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005714 final LinkProperties cellLp = new LinkProperties();
5715 cellLp.setInterfaceName(MOBILE_IFNAME);
5716 cellLp.addLinkAddress(myIpv6);
5717 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5718 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005719 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005720 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005721 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005722 reset(mMockNetd);
Chalard Jean587758b2019-11-29 16:41:50 +09005723 reset(mBatteryStatsService);
junyulai4a192e22018-06-13 15:00:37 +08005724 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5725 .thenReturn(getClatInterfaceConfig(myIpv4));
5726
Lorenzo Colittid593e292019-02-19 13:21:56 +09005727 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005728 mCellNetworkAgent.connect(true);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005729 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
Chalard Jean587758b2019-11-29 16:41:50 +09005730 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005731
5732 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
5733 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
Chalard Jean587758b2019-11-29 16:41:50 +09005734 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5735 TYPE_MOBILE);
Luke Huanga24d5d82019-04-09 18:41:49 +08005736
junyulai4a192e22018-06-13 15:00:37 +08005737 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005738 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005739
Lorenzo Colittid593e292019-02-19 13:21:56 +09005740 // Switching default network updates TCP buffer sizes.
5741 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5742
5743 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5744 // the NAT64 prefix was removed because one was never discovered.
5745 cellLp.addLinkAddress(myIpv4);
5746 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005747 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005748 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005749 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005750
Chalard Jean587758b2019-11-29 16:41:50 +09005751 // Make sure BatteryStats was not told about any v4- interfaces, as none should have
5752 // come online yet.
5753 waitForIdle();
5754 verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt());
5755
Lorenzo Colittid593e292019-02-19 13:21:56 +09005756 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005757 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005758 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005759 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005760
5761 // Remove IPv4 address. Expect prefix discovery to be started again.
5762 cellLp.removeLinkAddress(myIpv4);
5763 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5764 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005765 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005766 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005767
5768 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005769 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005770 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005771 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5772 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005773 LinkProperties lpBeforeClat = networkCallback.expectCallback(
Chalard Jean059c4262019-09-30 17:51:12 +09005774 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005775 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5776 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5777 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5778
5779 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005780 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean059c4262019-09-30 17:51:12 +09005781 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005782 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5783 .getStackedLinks();
5784 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5785
5786 // Change trivial linkproperties and see if stacked link is preserved.
5787 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5788 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005789 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005790
5791 List<LinkProperties> stackedLpsAfterChange =
5792 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5793 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5794 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5795
Luke Huang65914772019-03-16 00:31:46 +08005796 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005797 mResolverParamsParcelCaptor.capture());
5798 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5799 assertEquals(1, resolvrParams.servers.length);
5800 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08005801
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005802 for (final LinkProperties stackedLp : stackedLpsAfterChange) {
5803 verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(),
5804 TYPE_MOBILE);
5805 }
Chalard Jean587758b2019-11-29 16:41:50 +09005806
Lorenzo Colittid593e292019-02-19 13:21:56 +09005807 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5808 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005809 cellLp.addLinkAddress(myIpv4);
5810 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5811 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005812 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005813 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08005814 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005815
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005816 // As soon as stop is called, the linkproperties lose the stacked interface.
Chalard Jean059c4262019-09-30 17:51:12 +09005817 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005818 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
5819 LinkProperties expected = new LinkProperties(cellLp);
5820 expected.setNat64Prefix(kNat64Prefix);
5821 assertEquals(expected, actualLpAfterIpv4);
5822 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
5823
5824 // The interface removed callback happens but has no effect after stop is called.
5825 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5826 networkCallback.assertNoCallback();
5827
Lorenzo Colittid593e292019-02-19 13:21:56 +09005828 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005829 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005830 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005831 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005832
Lorenzo Colittid593e292019-02-19 13:21:56 +09005833 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5834 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5835 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005836 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5837 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005838
5839 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005840 cellLp.removeLinkAddress(myIpv4);
5841 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5842 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5843 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005844 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005845 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005846 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5847 kNat64PrefixString, 96);
Chalard Jean059c4262019-09-30 17:51:12 +09005848 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005849 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5850
Lorenzo Colittid593e292019-02-19 13:21:56 +09005851
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005852 // Clat iface comes up. Expect stacked link to be added.
5853 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005854 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5855 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005856
5857 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005858 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5859 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005860 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5861 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005862 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005863 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5864 (lp) -> lp.getStackedLinks().size() == 0);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005865
5866 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005867 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005868 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005869 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005870 mCm.unregisterNetworkCallback(networkCallback);
5871 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005872
5873 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005874 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08005875 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5876 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5877 .addCapability(NET_CAPABILITY_INTERNET)
5878 .build();
5879 mCm.registerNetworkCallback(networkRequest, networkCallback);
5880
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005881 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08005882 final LinkProperties cellLp = new LinkProperties();
5883 cellLp.setInterfaceName(MOBILE_IFNAME);
5884 mCellNetworkAgent.sendLinkProperties(cellLp);
5885 reset(mNetworkManagementService);
5886 mCellNetworkAgent.connect(true);
5887 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5888 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5889 eq(ConnectivityManager.TYPE_MOBILE));
5890
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005891 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005892 final LinkProperties wifiLp = new LinkProperties();
5893 wifiLp.setInterfaceName(WIFI_IFNAME);
5894 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5895
5896 // Network switch
5897 reset(mNetworkManagementService);
5898 mWiFiNetworkAgent.connect(true);
5899 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005900 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005901 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5902 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
5903 eq(ConnectivityManager.TYPE_WIFI));
5904 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
5905
5906 // Disconnect wifi and switch back to cell
5907 reset(mNetworkManagementService);
5908 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005909 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005910 assertNoCallbacks(networkCallback);
5911 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5912 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5913 eq(ConnectivityManager.TYPE_MOBILE));
5914
5915 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005916 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005917 wifiLp.setInterfaceName(WIFI_IFNAME);
5918 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5919 mWiFiNetworkAgent.connect(true);
5920 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005921 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005922 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
5923
5924 // Disconnect cell
5925 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005926 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08005927 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005928 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08005929 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
5930 // sent as network being switched. Ensure rule removal for cell will not be triggered
5931 // unexpectedly before network being removed.
5932 waitForIdle();
5933 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08005934 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
5935 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08005936 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08005937
5938 // Disconnect wifi
Chalard Jean407deb72019-11-19 16:14:30 +09005939 ConditionVariable cv = registerConnectivityBroadcast(1);
Chiachang Wanga6093042018-09-28 22:42:48 +08005940 reset(mNetworkManagementService);
5941 mWiFiNetworkAgent.disconnect();
5942 waitFor(cv);
5943 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
5944
5945 // Clean up
5946 mCm.unregisterNetworkCallback(networkCallback);
5947 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005948
Chalard Jeane7b24752019-06-20 16:01:19 +09005949 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005950 String[] values = tcpBufferSizes.split(",");
5951 String rmemValues = String.join(" ", values[0], values[1], values[2]);
5952 String wmemValues = String.join(" ", values[3], values[4], values[5]);
Chalard Jeane7b24752019-06-20 16:01:19 +09005953 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005954 reset(mMockNetd);
5955 }
5956
5957 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005958 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005959 final String testTcpBufferSizes = "1,2,3,4,5,6";
paulhu66269b32019-08-30 19:24:36 +08005960 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5961 .addTransportType(TRANSPORT_CELLULAR)
5962 .addCapability(NET_CAPABILITY_INTERNET)
5963 .build();
5964 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5965 mCm.registerNetworkCallback(networkRequest, networkCallback);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005966
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005967 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005968 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005969 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005970 mCellNetworkAgent.connect(false);
paulhu66269b32019-08-30 19:24:36 +08005971 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005972 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5973
5974 // Change link Properties should have updated tcp buffer size.
5975 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005976 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005977 mCellNetworkAgent.sendLinkProperties(lp);
Chalard Jean059c4262019-09-30 17:51:12 +09005978 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09005979 verifyTcpBufferSizeChange(testTcpBufferSizes);
paulhu66269b32019-08-30 19:24:36 +08005980
5981 // Clean up.
5982 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005983 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
paulhu66269b32019-08-30 19:24:36 +08005984 networkCallback.assertNoCallback();
5985 mCm.unregisterNetworkCallback(networkCallback);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08005986 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005987
5988 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005989 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005990 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005991 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005992 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
5993 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
5994 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
5995 }
5996
5997 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005998 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00005999 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006000 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006001 mWiFiNetworkAgent.connect(true);
6002 waitForIdle();
6003 assertNull(mService.getProxyForNetwork(null));
6004
6005 final LinkProperties testLinkProperties = new LinkProperties();
6006 testLinkProperties.setHttpProxy(testProxyInfo);
6007
6008 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6009 waitForIdle();
6010
6011 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6012 }
6013
6014 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006015 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006016 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6017
6018 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006019 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006020 mWiFiNetworkAgent.connect(true);
6021 waitForIdle();
6022 assertNull(mService.getProxyForNetwork(null));
6023
6024 // Set up a VPN network with a proxy
6025 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006026 final TestNetworkAgentWrapper
6027 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006028 final ArraySet<UidRange> ranges = new ArraySet<>();
6029 ranges.add(new UidRange(uid, uid));
6030 mMockVpn.setUids(ranges);
6031 LinkProperties testLinkProperties = new LinkProperties();
6032 testLinkProperties.setHttpProxy(testProxyInfo);
6033 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6034 waitForIdle();
6035
6036 // Connect to VPN with proxy
6037 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6038 vpnNetworkAgent.connect(true);
6039 mMockVpn.connect();
6040 waitForIdle();
6041
6042 // Test that the VPN network returns a proxy, and the WiFi does not.
6043 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6044 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6045 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6046
6047 // Test that the VPN network returns no proxy when it is set to null.
6048 testLinkProperties.setHttpProxy(null);
6049 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6050 waitForIdle();
6051 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6052 assertNull(mService.getProxyForNetwork(null));
6053
6054 // Set WiFi proxy and check that the vpn proxy is still null.
6055 testLinkProperties.setHttpProxy(testProxyInfo);
6056 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6057 waitForIdle();
6058 assertNull(mService.getProxyForNetwork(null));
6059
6060 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6061 // correct proxy setting.
6062 vpnNetworkAgent.disconnect();
6063 waitForIdle();
6064 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6065 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6066 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6067 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006068
6069 @Test
6070 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6071 LinkProperties lp = new LinkProperties();
6072 lp.setInterfaceName("tun0");
6073 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6074 // The uid range needs to cover the test app so the network is visible to it.
6075 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006076 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006077
6078 // Connected VPN should have interface rules set up. There are two expected invocations,
6079 // one during VPN uid update, one during VPN LinkProperties update
6080 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6081 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6082 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6083 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6084 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6085
6086 vpnNetworkAgent.disconnect();
6087 waitForIdle();
6088
6089 // Disconnected VPN should have interface rules removed
6090 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6091 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6092 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6093 }
6094
6095 @Test
6096 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6097 LinkProperties lp = new LinkProperties();
6098 lp.setInterfaceName("tun0");
6099 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6100 // The uid range needs to cover the test app so the network is visible to it.
6101 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006102 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6103 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006104
6105 // Legacy VPN should not have interface rules set up
6106 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6107 }
6108
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09006109 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006110 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6111 throws Exception {
6112 LinkProperties lp = new LinkProperties();
6113 lp.setInterfaceName("tun0");
6114 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6115 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6116 // The uid range needs to cover the test app so the network is visible to it.
6117 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006118 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6119 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006120
6121 // IPv6 unreachable route should not be misinterpreted as a default route
6122 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6123 }
6124
6125 @Test
6126 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6127 LinkProperties lp = new LinkProperties();
6128 lp.setInterfaceName("tun0");
6129 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6130 // The uid range needs to cover the test app so the network is visible to it.
6131 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006132 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006133
6134 // Connected VPN should have interface rules set up. There are two expected invocations,
6135 // one during VPN uid update, one during VPN LinkProperties update
6136 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6137 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6138 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6139 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6140
6141 reset(mMockNetd);
6142 InOrder inOrder = inOrder(mMockNetd);
6143 lp.setInterfaceName("tun1");
6144 vpnNetworkAgent.sendLinkProperties(lp);
6145 waitForIdle();
6146 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6147 // removed first, then new rules added)
6148 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6149 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6150 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6151 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6152
6153 reset(mMockNetd);
6154 lp = new LinkProperties();
6155 lp.setInterfaceName("tun1");
6156 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6157 vpnNetworkAgent.sendLinkProperties(lp);
6158 waitForIdle();
6159 // VPN not routing everything should no longer have interface filtering rules
6160 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6161 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6162
6163 reset(mMockNetd);
6164 lp = new LinkProperties();
6165 lp.setInterfaceName("tun1");
6166 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6167 vpnNetworkAgent.sendLinkProperties(lp);
6168 waitForIdle();
6169 // Back to routing all IPv6 traffic should have filtering rules
6170 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6171 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6172 }
6173
6174 @Test
6175 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6176 LinkProperties lp = new LinkProperties();
6177 lp.setInterfaceName("tun0");
6178 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6179 // The uid range needs to cover the test app so the network is visible to it.
6180 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006181 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006182 Collections.singleton(vpnRange));
6183
6184 reset(mMockNetd);
6185 InOrder inOrder = inOrder(mMockNetd);
6186
6187 // Update to new range which is old range minus APP1, i.e. only APP2
6188 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6189 new UidRange(vpnRange.start, APP1_UID - 1),
6190 new UidRange(APP1_UID + 1, vpnRange.stop)));
6191 vpnNetworkAgent.setUids(newRanges);
6192 waitForIdle();
6193
6194 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6195 // Verify old rules are removed before new rules are added
6196 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6197 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6198 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6199 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6200 }
6201
Valentin Iftimec86ebba2019-09-24 13:32:13 +02006202 @Test
6203 public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
6204 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6205
6206 LinkProperties wifiLp = new LinkProperties();
6207 wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
6208 wifiLp.setWakeOnLanSupported(false);
6209
6210 // Default network switch should update ifaces.
6211 mWiFiNetworkAgent.connect(false);
6212 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6213 waitForIdle();
6214
6215 // ConnectivityService should have changed the WakeOnLanSupported to true
6216 wifiLp.setWakeOnLanSupported(true);
6217 assertEquals(wifiLp, mService.getActiveLinkProperties());
6218 }
6219
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006220
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006221 private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
Chalard Jeane7b24752019-06-20 16:01:19 +09006222 Set<UidRange> vpnRange) throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006223 final TestNetworkAgentWrapper
6224 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006225 vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
6226 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6227 mMockVpn.connect();
6228 mMockVpn.setUids(vpnRange);
6229 vpnNetworkAgent.connect(true);
6230 waitForIdle();
6231 return vpnNetworkAgent;
6232 }
6233
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006234 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6235 final PackageInfo packageInfo = new PackageInfo();
paulhu86e23eb2019-11-05 18:05:05 +08006236 if (hasSystemPermission) {
6237 packageInfo.requestedPermissions = new String[] {
6238 CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
6239 packageInfo.requestedPermissionsFlags = new int[] {
6240 REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
6241 } else {
6242 packageInfo.requestedPermissions = new String[0];
6243 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006244 packageInfo.applicationInfo = new ApplicationInfo();
6245 packageInfo.applicationInfo.privateFlags = 0;
6246 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6247 UserHandle.getAppId(uid));
6248 return packageInfo;
6249 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006250}