blob: a5554c740e7f7f42d61e9f2f670937549d08656e [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 VANead1ef42019-12-17 16:45:42 +090024import static android.content.pm.PackageManager.PERMISSION_DENIED;
25import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090026import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
Erik Klinef851d6d2015-04-20 16:03:48 +090027import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Chalard Jean9ca13772019-11-15 12:08:36 +090028import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
29import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090030import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070031import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
32import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
33import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090034import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070035import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090036import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
37import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Chalard Jean9ca13772019-11-15 12:08:36 +090038import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
Lorenzo Colitti1cfd6b62021-01-28 18:31:31 +090039import static android.net.ConnectivityManager.TYPE_VPN;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070040import static android.net.ConnectivityManager.TYPE_WIFI;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080041import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
42import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
43import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
44import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
lucaslin783f2212019-10-22 18:27:33 +080045import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080046import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
47import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060048import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
52import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
53import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
54import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
55import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
57import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
58import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
59import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090060import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060061import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080062import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060063import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
64import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
65import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
66import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
67import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
68import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
69import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
70import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090071import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060072import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
73import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080074import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
75import static android.net.NetworkPolicyManager.RULE_NONE;
76import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
77import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000078import static android.net.RouteInfo.RTN_UNREACHABLE;
Cody Kesting0d8d6ac2020-05-12 18:47:10 +000079import static android.os.Process.INVALID_UID;
Benedict Wong5d50ce82020-01-20 22:14:59 -080080import static android.system.OsConstants.IPPROTO_TCP;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060081
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090082import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090083import static com.android.testutils.ConcurrentUtilsKt.await;
84import static com.android.testutils.ConcurrentUtilsKt.durationOf;
Chalard Jeane7b24752019-06-20 16:01:19 +090085import static com.android.testutils.ExceptionUtils.ignoreExceptions;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090086import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
87import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
88import static com.android.testutils.MiscAssertsKt.assertEmpty;
89import static com.android.testutils.MiscAssertsKt.assertLength;
90import static com.android.testutils.MiscAssertsKt.assertRunsInAtMost;
91import static com.android.testutils.MiscAssertsKt.assertThrows;
92
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090093import static org.junit.Assert.assertEquals;
94import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080095import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090096import static org.junit.Assert.assertNotNull;
97import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060098import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090099import static org.junit.Assert.fail;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900100import static org.mockito.ArgumentMatchers.anyLong;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900101import static org.mockito.ArgumentMatchers.anyString;
Cody Kestinga3b71c42020-02-11 10:03:26 -0800102import static org.mockito.ArgumentMatchers.argThat;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000103import static org.mockito.ArgumentMatchers.eq;
Chiachang Wang4d2791b2020-06-16 01:02:52 +0000104import static org.mockito.ArgumentMatchers.isNull;
Chalard Jean587758b2019-11-29 16:41:50 +0900105import static org.mockito.ArgumentMatchers.startsWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900106import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +0900107import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600108import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900109import static org.mockito.Mockito.doAnswer;
110import static org.mockito.Mockito.doNothing;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900111import static org.mockito.Mockito.doReturn;
Roshan Piuse38acab2020-01-16 12:17:17 -0800112import static org.mockito.Mockito.doThrow;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000113import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -0800114import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600115import static org.mockito.Mockito.never;
116import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900117import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900118import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +0900119import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600120import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -0700121import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900122import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700123
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900124import android.Manifest;
junyulai7c469172019-01-16 20:23:34 +0800125import android.annotation.NonNull;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900126import android.app.AlarmManager;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800127import android.app.AppOpsManager;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900128import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400129import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400130import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900131import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900132import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700133import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400134import android.content.Intent;
135import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000136import android.content.pm.ApplicationInfo;
137import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100138import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000139import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900140import android.content.res.Resources;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800141import android.location.LocationManager;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900142import android.net.CaptivePortalData;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800143import android.net.ConnectionInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400144import android.net.ConnectivityManager;
145import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900146import android.net.ConnectivityManager.PacketKeepalive;
147import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900148import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900149import android.net.ConnectivityThread;
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000150import android.net.DataStallReportParcelable;
Cody Kesting63e4e002019-12-18 10:57:50 -0800151import android.net.IConnectivityDiagnosticsCallback;
Luke Huang65914772019-03-16 00:31:46 +0800152import android.net.IDnsResolver;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900153import android.net.IIpConnectivityMetrics;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800154import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900155import android.net.INetworkMonitor;
156import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800157import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700158import android.net.INetworkPolicyManager;
159import android.net.INetworkStatsService;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800160import android.net.InetAddresses;
junyulai4a192e22018-06-13 15:00:37 +0800161import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900162import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800163import android.net.IpSecManager;
164import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900165import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700166import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700167import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400168import android.net.Network;
Chiachang Wang4d2791b2020-06-16 01:02:52 +0000169import android.net.NetworkAgent;
170import android.net.NetworkAgentConfig;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400171import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700172import android.net.NetworkFactory;
Chalard Jean9ca13772019-11-15 12:08:36 +0900173import android.net.NetworkInfo;
Lorenzo Colittid590e33e2021-01-06 01:36:07 +0900174import android.net.NetworkInfo.DetailedState;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400175import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700176import android.net.NetworkSpecifier;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900177import android.net.NetworkStack;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900178import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800179import android.net.NetworkState;
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000180import android.net.NetworkTestResultParcelable;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100181import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000182import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800183import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700184import android.net.RouteInfo;
Lorenzo Colittid86407b2020-03-18 07:52:25 +0000185import android.net.RouteInfoParcel;
junyulai48eac1d42018-12-27 17:25:29 +0800186import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900187import android.net.UidRange;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900188import android.net.Uri;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800189import android.net.VpnManager;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900190import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900191import android.net.shared.NetworkMonitorUtils;
192import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900193import android.net.util.MultinetworkPolicyTracker;
Chalard Jean751bb3f2019-06-19 23:29:58 +0900194import android.os.BadParcelableException;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100195import android.os.Binder;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800196import android.os.Build;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900197import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400198import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700199import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700200import android.os.HandlerThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800201import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700202import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900203import android.os.Looper;
Etan Cohena7434272017-04-03 12:17:51 -0700204import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800205import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700206import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000207import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800208import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900209import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900210import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000211import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900212import android.provider.Settings;
Benedict Wongb570e862020-01-17 19:33:55 -0800213import android.security.KeyStore;
junyulai0c666972019-03-04 22:45:36 +0800214import android.system.Os;
Hall Liued6d6e62020-03-26 19:09:30 -0700215import android.telephony.TelephonyManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900216import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800217import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100218import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700219import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800220import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700221
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800222import androidx.test.InstrumentationRegistry;
Guang Zhub90866d2019-09-01 21:37:04 -0700223import androidx.test.filters.FlakyTest;
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800224import androidx.test.filters.SmallTest;
225import androidx.test.runner.AndroidJUnit4;
226
Chalard Jean587758b2019-11-29 16:41:50 +0900227import com.android.internal.app.IBatteryStats;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900228import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800229import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900230import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900231import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900232import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900233import com.android.internal.util.test.FakeSettingsProvider;
Cody Kesting63e4e002019-12-18 10:57:50 -0800234import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
Chalard Jeandda156a2018-01-10 21:19:32 +0900235import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900236import com.android.server.connectivity.DefaultNetworkMetrics;
237import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900238import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800239import com.android.server.connectivity.Nat464Xlat;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800240import com.android.server.connectivity.NetworkAgentInfo;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900241import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000242import com.android.server.connectivity.ProxyTracker;
Chalard Jeandda156a2018-01-10 21:19:32 +0900243import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900244import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900245import com.android.server.net.NetworkPolicyManagerInternal;
Chalard Jeane7b24752019-06-20 16:01:19 +0900246import com.android.testutils.ExceptionUtils;
Chalard Jeance75e0e2019-05-28 16:48:32 +0900247import com.android.testutils.HandlerUtilsKt;
Chalard Jean059c4262019-09-30 17:51:12 +0900248import com.android.testutils.RecorderCallback.CallbackEntry;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900249import com.android.testutils.TestableNetworkCallback;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400250
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900251import org.junit.After;
252import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900253import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900254import org.junit.Test;
255import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900256import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000257import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900258import org.mockito.Mock;
259import org.mockito.MockitoAnnotations;
260import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900261import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900262
junyulai0c666972019-03-04 22:45:36 +0800263import java.io.IOException;
264import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800265import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000266import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700267import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900268import java.net.InetSocketAddress;
269import java.net.Socket;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400270import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900271import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100272import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800273import java.util.Collections;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900274import java.util.HashMap;
dalyk1fcb7392018-03-05 12:42:22 -0500275import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100276import java.util.List;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900277import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100278import java.util.Set;
Lorenzo Colittid590e33e2021-01-06 01:36:07 +0900279import java.util.concurrent.CompletableFuture;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900280import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800281import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800282import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800283import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900284import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900285import java.util.concurrent.TimeUnit;
Lorenzo Colittid590e33e2021-01-06 01:36:07 +0900286import java.util.concurrent.TimeoutException;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700287import java.util.concurrent.atomic.AtomicBoolean;
Lorenzo Colittid590e33e2021-01-06 01:36:07 +0900288import java.util.concurrent.atomic.AtomicReference;
Chalard Jean9ca13772019-11-15 12:08:36 +0900289import java.util.function.Predicate;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800290import java.util.function.Supplier;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900291
292import kotlin.reflect.KClass;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700293
294/**
295 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400296 *
297 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900298 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700299 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900300@RunWith(AndroidJUnit4.class)
301@SmallTest
302public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700303 private static final String TAG = "ConnectivityServiceTest";
304
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900305 private static final int TIMEOUT_MS = 500;
Chalard Jeanb299b842019-09-27 17:13:14 +0900306 private static final int TEST_LINGER_DELAY_MS = 300;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900307 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
308 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
309 // timeout. For this, our assertions should run fast enough to leave less than
310 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
311 // supposedly fired, and the time we call expectCallback.
Chalard Jeanb299b842019-09-27 17:13:14 +0900312 private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900313 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
314 // complete before callbacks are verified.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900315 private static final int TEST_REQUEST_TIMEOUT_MS = 150;
316
317 private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900318
Cody Kestinga75e26b2020-01-05 14:06:39 -0800319 private static final long TIMESTAMP = 1234L;
320
Cody Kesting3096b662020-03-18 21:11:29 +0000321 private static final int NET_ID = 110;
322
junyulai4a192e22018-06-13 15:00:37 +0800323 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700324 private static final String MOBILE_IFNAME = "test_rmnet_data0";
325 private static final String WIFI_IFNAME = "test_wlan0";
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200326 private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
Lorenzo Colittia2e63632020-11-16 16:05:44 +0900327 private static final String VPN_IFNAME = "tun10042";
Roshan Piuse38acab2020-01-16 12:17:17 -0800328 private static final String TEST_PACKAGE_NAME = "com.android.test.package";
Luke Huang65914772019-03-16 00:31:46 +0800329 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700330
Cody Kesting560eb262020-02-12 14:50:58 -0800331 private static final String INTERFACE_NAME = "interface";
332
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900333 private MockContext mServiceContext;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900334 private HandlerThread mCsHandlerThread;
335 private ConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900336 private WrappedConnectivityManager mCm;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900337 private TestNetworkAgentWrapper mWiFiNetworkAgent;
338 private TestNetworkAgentWrapper mCellNetworkAgent;
339 private TestNetworkAgentWrapper mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900340 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900341 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800342 private INetworkPolicyListener mPolicyListener;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900343 private WrappedMultinetworkPolicyTracker mPolicyTracker;
344 private HandlerThread mAlarmManagerThread;
Lorenzo Colitti590e2962020-11-16 10:11:12 +0900345 private TestNetIdManager mNetIdManager;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700346
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900347 @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
Hugo Benichi64901e52017-10-19 14:42:40 +0900348 @Mock IpConnectivityMetrics.Logger mMetricsService;
349 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900350 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600351 @Mock INetworkStatsService mStatsService;
Chalard Jean587758b2019-11-29 16:41:50 +0900352 @Mock IBatteryStats mBatteryStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800353 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800354 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800355 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900356 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100357 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000358 @Mock UserManager mUserManager;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900359 @Mock NotificationManager mNotificationManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900360 @Mock AlarmManager mAlarmManager;
Cody Kesting63e4e002019-12-18 10:57:50 -0800361 @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
362 @Mock IBinder mIBinder;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800363 @Mock LocationManager mLocationManager;
364 @Mock AppOpsManager mAppOpsManager;
Hall Liued6d6e62020-03-26 19:09:30 -0700365 @Mock TelephonyManager mTelephonyManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900366
waynema13516842019-03-12 18:13:49 +0800367 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
368 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900369
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900370 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
371 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
372 // reflect the state of our test ConnectivityService.
373 private class WrappedConnectivityManager extends ConnectivityManager {
374 private Network mFakeBoundNetwork;
375
376 public synchronized boolean bindProcessToNetwork(Network network) {
377 mFakeBoundNetwork = network;
378 return true;
379 }
380
381 public synchronized Network getBoundNetworkForProcess() {
382 return mFakeBoundNetwork;
383 }
384
385 public WrappedConnectivityManager(Context context, ConnectivityService service) {
386 super(context, service);
387 }
388 }
389
Paul Jensend7b6ca92015-05-13 14:05:12 -0400390 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900391 private final MockContentResolver mContentResolver;
392
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900393 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900394 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900395 // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
396 private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900397
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900398 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400399 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900400
401 mResources = spy(base.getResources());
402 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
403 thenReturn(new String[] {
404 "wifi,1,1,1,-1,true",
405 "mobile,0,0,0,-1,true",
406 "mobile_mms,2,0,2,60000,true",
Chalard Jean9ca13772019-11-15 12:08:36 +0900407 "mobile_supl,3,0,2,60000,true",
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900408 });
409
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200410 when(mResources.getStringArray(
411 com.android.internal.R.array.config_wakeonlan_supported_interfaces))
412 .thenReturn(new String[]{
413 WIFI_WOL_IFNAME,
414 });
415
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900416 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900417 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400418 }
419
420 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900421 public void startActivityAsUser(Intent intent, UserHandle handle) {
422 mStartedActivities.offer(intent);
423 }
424
Chalard Jeanf30d1e12019-06-27 08:24:51 +0000425 public Intent expectStartActivityIntent(int timeoutMs) {
426 Intent intent = null;
427 try {
428 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
429 } catch (InterruptedException e) {}
430 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
431 return intent;
432 }
433
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900434 public void expectNoStartActivityIntent(int timeoutMs) {
435 try {
436 assertNull("Received unexpected Intent to start activity",
437 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
438 } catch (InterruptedException e) {}
439 }
440
441 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900442 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900443 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900444 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000445 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900446 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800447 if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
448 if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
Hall Liued6d6e62020-03-26 19:09:30 -0700449 if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400450 return super.getSystemService(name);
451 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900452
453 @Override
454 public ContentResolver getContentResolver() {
455 return mContentResolver;
456 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900457
458 @Override
459 public Resources getResources() {
460 return mResources;
461 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100462
463 @Override
464 public PackageManager getPackageManager() {
465 return mPackageManager;
466 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900467
Benedict Wong5d50ce82020-01-20 22:14:59 -0800468 private int checkMockedPermission(String permission, Supplier<Integer> ifAbsent) {
469 final Integer granted = mMockedPermissions.get(permission);
470 return granted != null ? granted : ifAbsent.get();
471 }
472
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900473 @Override
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900474 public int checkPermission(String permission, int pid, int uid) {
Benedict Wong5d50ce82020-01-20 22:14:59 -0800475 return checkMockedPermission(
476 permission, () -> super.checkPermission(permission, pid, uid));
477 }
478
479 @Override
480 public int checkCallingOrSelfPermission(String permission) {
481 return checkMockedPermission(
482 permission, () -> super.checkCallingOrSelfPermission(permission));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900483 }
484
485 @Override
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900486 public void enforceCallingOrSelfPermission(String permission, String message) {
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900487 final Integer granted = mMockedPermissions.get(permission);
488 if (granted == null) {
489 super.enforceCallingOrSelfPermission(permission, message);
490 return;
491 }
492
493 if (!granted.equals(PERMISSION_GRANTED)) {
494 throw new SecurityException("[Test] permission denied: " + permission);
495 }
496 }
497
498 /**
499 * Mock checks for the specified permission, and have them behave as per {@code granted}.
500 *
501 * <p>Passing null reverts to default behavior, which does a real permission check on the
502 * test package.
503 * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
504 * {@link PackageManager#PERMISSION_DENIED}.
505 */
506 public void setPermission(String permission, Integer granted) {
507 mMockedPermissions.put(permission, granted);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900508 }
509 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400510
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900511 private void waitForIdle() {
512 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
513 waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
514 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
515 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
516 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
517 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Hugo Benichibb91c572017-05-22 10:44:02 +0900518 }
519
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900520 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900521 if (agent == null) {
522 return;
523 }
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900524 agent.waitForIdle(timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900525 }
526
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900527 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +0900528 public void testWaitForIdle() throws Exception {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900529 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
530
531 // Tests that waitForIdle returns immediately if the service is already idle.
532 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900533 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900534 }
535
536 // Bring up a network that we can use to send messages to ConnectivityService.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +0900537 ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900538 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900539 mWiFiNetworkAgent.connect(false);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +0900540 b.expectBroadcast();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900541 Network n = mWiFiNetworkAgent.getNetwork();
542 assertNotNull(n);
543
544 // Tests that calling waitForIdle waits for messages to be processed.
545 for (int i = 0; i < attempts; i++) {
546 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900547 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900548 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
549 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900550 }
551
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900552 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
553 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800554 @Ignore
Chalard Jeane7b24752019-06-20 16:01:19 +0900555 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900556 // Bring up a network that we can use to send messages to ConnectivityService.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +0900557 ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900558 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Hugo Benichi5d540d12016-10-17 15:54:51 +0900559 mWiFiNetworkAgent.connect(false);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +0900560 b.expectBroadcast();
Hugo Benichi5d540d12016-10-17 15:54:51 +0900561 Network n = mWiFiNetworkAgent.getNetwork();
562 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900563
564 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900565 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900566 for (int i = 0; i < attempts; i++) {
567 mWiFiNetworkAgent.setSignalStrength(i);
568 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
569 // We hit a race condition, as expected. Pass the test.
570 return;
571 }
572 }
573
574 // No race? There is a bug in this test.
575 fail("expected race condition at least once in " + attempts + " attempts");
576 }
577
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900578 private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800579 private static final int VALIDATION_RESULT_INVALID = 0;
580
Cody Kesting4f49f142020-01-06 16:55:35 -0800581 private static final long DATA_STALL_TIMESTAMP = 10L;
582 private static final int DATA_STALL_DETECTION_METHOD = 1;
583
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900584 private INetworkMonitor mNetworkMonitor;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900585 private INetworkMonitorCallbacks mNmCallbacks;
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000586 private int mNmValidationResult = VALIDATION_RESULT_INVALID;
lucaslin783f2212019-10-22 18:27:33 +0800587 private int mProbesCompleted;
588 private int mProbesSucceeded;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900589 private String mNmValidationRedirectUrl = null;
590 private boolean mNmProvNotificationRequested = false;
591
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900592 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
593 // Contains the redirectUrl from networkStatus(). Before reading, wait for
594 // mNetworkStatusReceived.
595 private String mRedirectUrl;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900596
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900597 TestNetworkAgentWrapper(int transport) throws Exception {
Lorenzo Colittiabb9e372020-11-18 22:50:57 +0900598 this(transport, new LinkProperties(), null);
Rubin Xu1bb5c082017-09-05 18:40:49 +0100599 }
600
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900601 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
602 throws Exception {
Lorenzo Colittiabb9e372020-11-18 22:50:57 +0900603 this(transport, linkProperties, null);
604 }
605
606 private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
607 NetworkCapabilities ncTemplate) throws Exception {
608 super(transport, linkProperties, ncTemplate, mServiceContext);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900609
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900610 // Waits for the NetworkAgent to be registered, which includes the creation of the
611 // NetworkMonitor.
612 waitForIdle(TIMEOUT_MS);
Chalard Jean3da8e0f2019-09-20 17:19:31 +0900613 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
614 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900615 }
616
617 @Override
618 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
619 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900620 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900621
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900622 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900623 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900624 return null;
625 };
626
Chalard Jeane7b24752019-06-20 16:01:19 +0900627 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
628 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900629
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900630 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900631 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
632 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
633 doNothing().when(mNetworkStack).makeNetworkMonitor(
634 nmNetworkCaptor.capture(),
635 any() /* name */,
636 nmCbCaptor.capture());
637
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900638 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400639 @Override
640 public void networkStatus(int status, String redirectUrl) {
641 mRedirectUrl = redirectUrl;
642 mNetworkStatusReceived.open();
643 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400644 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900645
Chalard Jean29c6e0c2020-01-16 17:13:26 +0900646 assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900647 mNmCallbacks = nmCbCaptor.getValue();
648
Chalard Jeane7b24752019-06-20 16:01:19 +0900649 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900650
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900651 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900652 }
653
Chalard Jeane7b24752019-06-20 16:01:19 +0900654 private void onValidationRequested() throws Exception {
655 if (mNmProvNotificationRequested
656 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
657 mNmCallbacks.hideProvisioningNotification();
658 mNmProvNotificationRequested = false;
659 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900660
lucaslin783f2212019-10-22 18:27:33 +0800661 mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000662 final NetworkTestResultParcelable p = new NetworkTestResultParcelable();
663 p.result = mNmValidationResult;
664 p.probesAttempted = mProbesCompleted;
665 p.probesSucceeded = mProbesSucceeded;
666 p.redirectUrl = mNmValidationRedirectUrl;
667 p.timestampMillis = TIMESTAMP;
668 mNmCallbacks.notifyNetworkTestedWithExtras(p);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900669
Chalard Jeane7b24752019-06-20 16:01:19 +0900670 if (mNmValidationRedirectUrl != null) {
671 mNmCallbacks.showProvisioningNotification(
Roshan Piuse38acab2020-01-16 12:17:17 -0800672 "test_provisioning_notif_action", TEST_PACKAGE_NAME);
Chalard Jeane7b24752019-06-20 16:01:19 +0900673 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900674 }
Paul Jensen3d911462015-06-12 06:40:24 -0400675 }
676
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900677 /**
678 * Connect without adding any internet capability.
679 */
Paul Jensene0988542015-06-25 15:30:08 -0400680 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900681 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400682 }
683
Paul Jensend7b6ca92015-05-13 14:05:12 -0400684 /**
Paul Jensene0988542015-06-25 15:30:08 -0400685 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400686 * @param validated Indicate if network should pretend to be validated.
687 */
688 public void connect(boolean validated) {
lucaslin783f2212019-10-22 18:27:33 +0800689 connect(validated, true, false /* isStrictMode */);
Hugo Benichi16f0a942017-06-20 14:07:59 +0900690 }
691
692 /**
693 * Transition this NetworkAgent to CONNECTED state.
694 * @param validated Indicate if network should pretend to be validated.
695 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
696 */
lucaslin783f2212019-10-22 18:27:33 +0800697 public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900698 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400699
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900700 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400701 final ConditionVariable validatedCv = new ConditionVariable();
702 if (validated) {
lucaslin783f2212019-10-22 18:27:33 +0800703 setNetworkValid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400704 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900705 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900706 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400707 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900708 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400709 public void onCapabilitiesChanged(Network network,
710 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400711 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900712 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400713 validatedCv.open();
714 }
715 }
716 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400717 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400718 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900719 if (hasInternet) {
720 addCapability(NET_CAPABILITY_INTERNET);
721 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400722
Paul Jensene0988542015-06-25 15:30:08 -0400723 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400724
725 if (validated) {
726 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400727 waitFor(validatedCv);
lucaslin783f2212019-10-22 18:27:33 +0800728 setNetworkInvalid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400729 }
730
731 if (callback != null) mCm.unregisterNetworkCallback(callback);
732 }
733
lucaslin783f2212019-10-22 18:27:33 +0800734 public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
735 setNetworkPortal(redirectUrl, isStrictMode);
736 connect(false, true /* hasInternet */, isStrictMode);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400737 }
738
lucasline252a742019-03-12 13:08:03 +0800739 public void connectWithPartialConnectivity() {
740 setNetworkPartial();
741 connect(false);
742 }
743
lucaslin783f2212019-10-22 18:27:33 +0800744 public void connectWithPartialValidConnectivity(boolean isStrictMode) {
745 setNetworkPartialValid(isStrictMode);
746 connect(false, true /* hasInternet */, isStrictMode);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900747 }
748
lucaslin783f2212019-10-22 18:27:33 +0800749 void setNetworkValid(boolean isStrictMode) {
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000750 mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900751 mNmValidationRedirectUrl = null;
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000752 int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS;
lucaslin783f2212019-10-22 18:27:33 +0800753 if (isStrictMode) {
754 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
755 }
756 // The probesCompleted equals to probesSucceeded for the case of valid network, so put
757 // the same value into two different parameter of the method.
758 setProbesStatus(probesSucceeded, probesSucceeded);
Erik Kline1d3db322017-02-28 16:20:20 +0900759 }
760
lucaslin783f2212019-10-22 18:27:33 +0800761 void setNetworkInvalid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900762 mNmValidationResult = VALIDATION_RESULT_INVALID;
763 mNmValidationRedirectUrl = null;
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000764 int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
765 | NETWORK_VALIDATION_PROBE_HTTP;
766 int probesSucceeded = 0;
lucaslin783f2212019-10-22 18:27:33 +0800767 // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
768 // tried to validate the private DNS but failed.
769 if (isStrictMode) {
770 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
771 probesSucceeded = probesCompleted;
772 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
773 }
774 setProbesStatus(probesCompleted, probesSucceeded);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900775 }
776
lucaslin783f2212019-10-22 18:27:33 +0800777 void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
778 setNetworkInvalid(isStrictMode);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900779 mNmValidationRedirectUrl = redirectUrl;
lucaslin783f2212019-10-22 18:27:33 +0800780 // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
781 // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000782 int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
lucaslin783f2212019-10-22 18:27:33 +0800783 int probesSucceeded = VALIDATION_RESULT_INVALID;
784 if (isStrictMode) {
785 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
786 }
787 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400788 }
789
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900790 void setNetworkPartial() {
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000791 mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900792 mNmValidationRedirectUrl = null;
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000793 int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
794 | NETWORK_VALIDATION_PROBE_FALLBACK;
795 int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK;
lucaslin783f2212019-10-22 18:27:33 +0800796 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400797 }
Paul Jensene0988542015-06-25 15:30:08 -0400798
lucaslin783f2212019-10-22 18:27:33 +0800799 void setNetworkPartialValid(boolean isStrictMode) {
800 setNetworkPartial();
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000801 mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID;
802 int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
803 | NETWORK_VALIDATION_PROBE_HTTP;
804 int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP;
lucaslin783f2212019-10-22 18:27:33 +0800805 // Suppose the partial network cannot pass the private DNS validation as well, so only
806 // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
807 if (isStrictMode) {
808 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
809 }
810 setProbesStatus(probesCompleted, probesSucceeded);
811 }
812
813 void setProbesStatus(int probesCompleted, int probesSucceeded) {
814 mProbesCompleted = probesCompleted;
815 mProbesSucceeded = probesSucceeded;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900816 }
Paul Jensen232437312016-04-06 09:51:26 -0400817
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +0900818 void notifyCaptivePortalDataChanged(CaptivePortalData data) {
819 try {
820 mNmCallbacks.notifyCaptivePortalDataChanged(data);
821 } catch (RemoteException e) {
822 throw new AssertionError("This cannot happen", e);
823 }
824 }
825
Paul Jensen232437312016-04-06 09:51:26 -0400826 public String waitForRedirectUrl() {
827 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
828 return mRedirectUrl;
829 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900830
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900831 public void expectDisconnected() {
832 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900833 }
834
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900835 public void expectPreventReconnectReceived() {
836 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900837 }
Cody Kesting4f49f142020-01-06 16:55:35 -0800838
839 void notifyDataStallSuspected() throws Exception {
Remi NGUYEN VAN24d8a332020-04-24 12:19:37 +0000840 final DataStallReportParcelable p = new DataStallReportParcelable();
841 p.detectionMethod = DATA_STALL_DETECTION_METHOD;
842 p.timestampMillis = DATA_STALL_TIMESTAMP;
843 mNmCallbacks.notifyDataStallSuspected(p);
Cody Kesting4f49f142020-01-06 16:55:35 -0800844 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400845 }
846
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900847 /**
848 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
849 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900850 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900851 * expectRemoveRequests.
852 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700853 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400854 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
855 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400856 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700857
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900858 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900859 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
860 // once, then cause some other thread to add or remove requests, then call
861 // waitForRequests().
862 // It is not possible to wait for both add and remove requests. When adding, the queue
863 // contains the expected score. When removing, the value is unused, all matters is the
864 // number of objects in the queue.
865 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900866
867 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900868 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900869 private boolean mExpectingAdditions;
870
Etan Cohenddb720a2019-01-08 12:09:18 -0800871 // Used to collect the networks requests managed by this factory. This is a duplicate of
872 // the internal information stored in the NetworkFactory (which is private).
873 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
874
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700875 public MockNetworkFactory(Looper looper, Context context, String logTag,
876 NetworkCapabilities filter) {
877 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900878 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700879 }
880
881 public int getMyRequestCount() {
882 return getRequestCount();
883 }
884
885 protected void startNetwork() {
886 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400887 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700888 }
889
890 protected void stopNetwork() {
891 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400892 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700893 }
894
895 public boolean getMyStartRequested() {
896 return mNetworkStarted.get();
897 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400898
899 public ConditionVariable getNetworkStartedCV() {
900 mNetworkStartedCV.close();
901 return mNetworkStartedCV;
902 }
903
904 public ConditionVariable getNetworkStoppedCV() {
905 mNetworkStoppedCV.close();
906 return mNetworkStoppedCV;
907 }
908
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900909 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900910 protected void handleAddRequest(NetworkRequest request, int score,
911 int factorySerialNumber) {
912 synchronized (mExpectations) {
913 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900914
Chalard Jean05ab6812018-05-02 21:14:54 +0900915 assertNotNull("Added more requests than expected (" + request + " score : "
916 + score + ")", expectedScore);
917 // If we're expecting anything, we must be expecting additions.
918 if (!mExpectingAdditions) {
919 fail("Can't add requests while expecting requests to be removed");
920 }
921 if (expectedScore != score) {
922 fail("Expected score was " + expectedScore + " but actual was " + score
923 + " in added request");
924 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900925
Chalard Jean05ab6812018-05-02 21:14:54 +0900926 // Add the request.
927 mNetworkRequests.put(request.requestId, request);
928 super.handleAddRequest(request, score, factorySerialNumber);
929 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900930 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400931 }
932
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900933 @Override
934 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900935 synchronized (mExpectations) {
936 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900937
Chalard Jean05ab6812018-05-02 21:14:54 +0900938 assertTrue("Removed more requests than expected", expectedScore != null);
939 // If we're expecting anything, we must be expecting removals.
940 if (mExpectingAdditions) {
941 fail("Can't remove requests while expecting requests to be added");
942 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900943
Chalard Jean05ab6812018-05-02 21:14:54 +0900944 // Remove the request.
945 mNetworkRequests.remove(request.requestId);
946 super.handleRemoveRequest(request);
947 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900948 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400949 }
950
Etan Cohenddb720a2019-01-08 12:09:18 -0800951 // Trigger releasing the request as unfulfillable
952 public void triggerUnfulfillable(NetworkRequest r) {
953 super.releaseRequestAsUnfulfillableByAnyFactory(r);
954 }
955
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900956 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900957 if (mExpectations.size() != 0) {
958 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900959 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400960 }
961
Chalard Jean05ab6812018-05-02 21:14:54 +0900962 // Expects that requests with the specified scores will be added.
963 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900964 assertNoExpectations();
965 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900966 for (int score : scores) {
967 mExpectations.add(score);
968 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400969 }
970
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900971 // Expects that count requests will be removed.
972 public void expectRemoveRequests(final int count) {
973 assertNoExpectations();
974 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900975 for (int i = 0; i < count; ++i) {
976 mExpectations.add(0); // For removals the score is ignored so any value will do.
977 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900978 }
979
980 // Waits for the expected request additions or removals to happen within a timeout.
981 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900982 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
983 synchronized (mExpectations) {
984 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
985 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
986 }
987 }
988 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900989 final String msg = count + " requests still not " +
990 (mExpectingAdditions ? "added" : "removed") +
991 " after " + TIMEOUT_MS + " ms";
992 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900993 }
994
Etan Cohenddb720a2019-01-08 12:09:18 -0800995 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
996 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900997 waitForRequests();
998 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800999 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -04001000 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001001 }
1002
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001003 private Set<UidRange> uidRangesForUid(int uid) {
1004 final ArraySet<UidRange> ranges = new ArraySet<>();
1005 ranges.add(new UidRange(uid, uid));
1006 return ranges;
1007 }
1008
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001009 private static Looper startHandlerThreadAndReturnLooper() {
1010 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
1011 handlerThread.start();
1012 return handlerThread.getLooper();
1013 }
1014
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001015 private class MockVpn extends Vpn implements TestableNetworkCallback.HasNetwork {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001016 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1017 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001018 private TestNetworkAgentWrapper mMockNetworkAgent;
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001019 private boolean mAgentRegistered = false;
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001020
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001021 private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
Cody Kestinga75e26b2020-01-05 14:06:39 -08001022 private VpnInfo mVpnInfo;
1023
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001024 public MockVpn(int userId) {
1025 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
Benedict Wongb570e862020-01-17 19:33:55 -08001026 userId, mock(KeyStore.class));
Lorenzo Colittia2e63632020-11-16 16:05:44 +09001027 mConfig = new VpnConfig();
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001028 }
1029
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001030 public void setUids(Set<UidRange> uids) {
1031 mNetworkCapabilities.setUids(uids);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001032 updateCapabilitiesInternal(null /* defaultNetwork */, true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001033 }
1034
Benedict Wong5d50ce82020-01-20 22:14:59 -08001035 public void setVpnType(int vpnType) {
1036 mVpnType = vpnType;
1037 }
1038
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001039 @Override
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001040 public Network getNetwork() {
1041 return (mMockNetworkAgent == null) ? null : mMockNetworkAgent.getNetwork();
1042 }
1043
1044 @Override
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001045 public int getNetId() {
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001046 return (mMockNetworkAgent == null) ? NETID_UNSET : mMockNetworkAgent.getNetwork().netId;
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001047 }
1048
1049 @Override
Benedict Wong5d50ce82020-01-20 22:14:59 -08001050 public int getActiveAppVpnType() {
1051 return mVpnType;
1052 }
1053
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001054 private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
1055 throws Exception {
1056 if (mAgentRegistered) throw new IllegalStateException("already registered");
1057 setUids(uids);
Varun Anandc51b06d2019-02-25 17:22:02 -08001058 mConfig.isMetered = isAlwaysMetered;
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001059 mInterface = VPN_IFNAME;
1060 mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
1061 mNetworkCapabilities);
1062 mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
1063 mAgentRegistered = true;
1064 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1065 mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
Varun Anandc51b06d2019-02-25 17:22:02 -08001066 }
1067
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001068 private void registerAgent(Set<UidRange> uids) throws Exception {
1069 registerAgent(false /* isAlwaysMetered */, uids, new LinkProperties());
Varun Anandc51b06d2019-02-25 17:22:02 -08001070 }
1071
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001072 private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
1073 mMockNetworkAgent.connect(validated, hasInternet, isStrictMode);
1074 }
1075
1076 private void connect(boolean validated) {
1077 mMockNetworkAgent.connect(validated);
1078 }
1079
1080 private TestNetworkAgentWrapper getAgent() {
1081 return mMockNetworkAgent;
1082 }
1083
1084 public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
1085 boolean hasInternet, boolean isStrictMode) throws Exception {
1086 mNetworkCapabilities.setOwnerUid(uid);
1087 mNetworkCapabilities.setAdministratorUids(new int[]{uid});
1088 registerAgent(false, ranges, lp);
1089 connect(validated, hasInternet, isStrictMode);
1090 waitForIdle();
1091 }
1092
1093 public void establish(LinkProperties lp, int uid, Set<UidRange> ranges) throws Exception {
1094 establish(lp, uid, ranges, true, true, false);
1095 }
1096
1097 public void establishForMyUid(LinkProperties lp) throws Exception {
1098 final int uid = Process.myUid();
1099 establish(lp, uid, uidRangesForUid(uid), true, true, false);
1100 }
1101
1102 public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)
1103 throws Exception {
1104 final int uid = Process.myUid();
1105 establish(new LinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet,
1106 isStrictMode);
1107 }
1108
1109 public void establishForMyUid() throws Exception {
1110 establishForMyUid(new LinkProperties());
1111 }
1112
1113 public void sendLinkProperties(LinkProperties lp) {
1114 mMockNetworkAgent.sendLinkProperties(lp);
1115 }
1116
1117 private NetworkCapabilities updateCapabilitiesInternal(Network defaultNetwork,
1118 boolean sendToConnectivityService) {
1119 if (!mAgentRegistered) return null;
1120 super.updateCapabilities(defaultNetwork);
1121 // Because super.updateCapabilities will update the capabilities of the agent but
1122 // not the mock agent, the mock agent needs to know about them.
1123 copyCapabilitiesToNetworkAgent(sendToConnectivityService);
1124 return new NetworkCapabilities(mNetworkCapabilities);
1125 }
1126
1127 private void copyCapabilitiesToNetworkAgent(boolean sendToConnectivityService) {
1128 if (null != mMockNetworkAgent) {
1129 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1130 sendToConnectivityService);
1131 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001132 }
1133
1134 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001135 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001136 return updateCapabilitiesInternal(defaultNetwork, false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001137 }
1138
1139 public void disconnect() {
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001140 if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect();
1141 mAgentRegistered = false;
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001142 }
Cody Kestinga75e26b2020-01-05 14:06:39 -08001143
1144 @Override
1145 public synchronized VpnInfo getVpnInfo() {
1146 if (mVpnInfo != null) return mVpnInfo;
1147
1148 return super.getVpnInfo();
1149 }
1150
Cody Kesting3096b662020-03-18 21:11:29 +00001151 private synchronized void setVpnInfo(VpnInfo vpnInfo) {
Cody Kestinga75e26b2020-01-05 14:06:39 -08001152 mVpnInfo = vpnInfo;
1153 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001154 }
1155
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001156 private void mockVpn(int uid) {
1157 synchronized (mService.mVpns) {
1158 int userId = UserHandle.getUserId(uid);
1159 mMockVpn = new MockVpn(userId);
1160 // This has no effect unless the VPN is actually connected, because things like
1161 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1162 // netId, and check if that network is actually connected.
1163 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001164 }
1165 }
1166
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001167 private void setUidRulesChanged(int uidRules) throws RemoteException {
1168 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1169 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001170
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001171 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
1172 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1173 }
1174
1175 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1176 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1177 }
1178
1179 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1180 volatile boolean mConfigRestrictsAvoidBadWifi;
1181 volatile int mConfigMeteredMultipathPreference;
1182
1183 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001184 super(c, h, r);
1185 }
1186
1187 @Override
1188 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001189 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +09001190 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001191
1192 @Override
1193 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001194 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +08001195 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001196 }
1197
Paul Jensen3d911462015-06-12 06:40:24 -04001198 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001199 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1200 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001201 */
1202 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001203 if (conditionVariable.block(TIMEOUT_MS)) {
1204 return;
1205 }
1206 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001207 }
1208
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001209 private static final int VPN_USER = 0;
1210 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1211 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1212 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1213
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001214 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001215 public void setUp() throws Exception {
Lorenzo Colitti590e2962020-11-16 10:11:12 +09001216 mNetIdManager = new TestNetIdManager();
1217
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001218 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001219
Hugo Benichi64901e52017-10-19 14:42:40 +09001220 MockitoAnnotations.initMocks(this);
1221 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1222
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001223 when(mUserManager.getUsers(eq(true))).thenReturn(
1224 Arrays.asList(new UserInfo[] {
1225 new UserInfo(VPN_USER, "", 0),
1226 }));
Qingxi Li9c5d8b92020-01-08 12:51:49 -08001227 final ApplicationInfo applicationInfo = new ApplicationInfo();
1228 applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1229 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
1230 .thenReturn(applicationInfo);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001231
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001232 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1233 // http://b/25897652 .
1234 if (Looper.myLooper() == null) {
1235 Looper.prepare();
1236 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001237 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001238
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001239 FakeSettingsProvider.clearSettingsProvider();
1240 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1241 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001242 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1243 LocalServices.addService(
1244 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001245
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001246 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1247 mAlarmManagerThread.start();
1248 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1249
1250 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1251 final ConnectivityService.Dependencies deps = makeDependencies();
1252 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001253 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001254 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001255 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001256 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001257 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001258 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001259 deps);
1260 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1261 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001262
Mike Yuf9729752018-08-17 15:22:05 +08001263 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1264 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1265 verify(mNpm).registerListener(policyListenerCaptor.capture());
1266 mPolicyListener = policyListenerCaptor.getValue();
1267
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001268 // Create local CM before sending system ready so that we can answer
1269 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001270 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001271 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001272 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001273 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001274
1275 // Ensure that the default setting for Captive Portals is used for most tests
1276 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001277 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001278 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001279 }
1280
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001281 private ConnectivityService.Dependencies makeDependencies() {
1282 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1283 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1284 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1285
1286 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1287 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
Lorenzo Colitti590e2962020-11-16 10:11:12 +09001288 doReturn(mNetIdManager).when(deps).makeNetIdManager();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001289 doReturn(mNetworkStack).when(deps).getNetworkStack();
1290 doReturn(systemProperties).when(deps).getSystemProperties();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001291 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1292 doReturn(mMetricsService).when(deps).getMetricsLogger();
1293 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1294 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
Chalard Jean587758b2019-11-29 16:41:50 +09001295 doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001296 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1297 doAnswer(inv -> {
1298 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1299 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1300 return mPolicyTracker;
1301 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1302
1303 return deps;
1304 }
1305
1306 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1307 doAnswer(inv -> {
1308 final long when = inv.getArgument(1);
1309 final WakeupMessage wakeupMsg = inv.getArgument(3);
1310 final Handler handler = inv.getArgument(4);
1311
1312 long delayMs = when - SystemClock.elapsedRealtime();
1313 if (delayMs < 0) delayMs = 0;
1314 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1315 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1316 + "ms into the future: " + delayMs);
1317 }
1318 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1319 delayMs);
1320
1321 return null;
1322 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1323 any(WakeupMessage.class), any());
1324
1325 doAnswer(inv -> {
1326 final WakeupMessage wakeupMsg = inv.getArgument(0);
1327 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1328 return null;
1329 }).when(am).cancel(any(WakeupMessage.class));
1330 }
1331
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001332 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001333 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001334 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001335 if (mCellNetworkAgent != null) {
1336 mCellNetworkAgent.disconnect();
1337 mCellNetworkAgent = null;
1338 }
1339 if (mWiFiNetworkAgent != null) {
1340 mWiFiNetworkAgent.disconnect();
1341 mWiFiNetworkAgent = null;
1342 }
1343 if (mEthernetNetworkAgent != null) {
1344 mEthernetNetworkAgent.disconnect();
1345 mEthernetNetworkAgent = null;
1346 }
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09001347 mMockVpn.disconnect();
1348 waitForIdle();
1349
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001350 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001351
1352 mCsHandlerThread.quitSafely();
1353 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001354 }
1355
Rubin Xu9e64dc02019-04-23 18:04:14 +01001356 private void mockDefaultPackages() throws Exception {
1357 final String testPackageName = mContext.getPackageName();
1358 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1359 testPackageName, PackageManager.GET_PERMISSIONS);
1360 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1361 new String[] {testPackageName});
1362 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1363 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1364
1365 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1366 Arrays.asList(new PackageInfo[] {
1367 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1368 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1369 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1370 }));
1371 }
1372
Paul Jensend7b6ca92015-05-13 14:05:12 -04001373 private void verifyActiveNetwork(int transport) {
1374 // Test getActiveNetworkInfo()
1375 assertNotNull(mCm.getActiveNetworkInfo());
1376 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1377 // Test getActiveNetwork()
1378 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001379 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001380 if (!NetworkCapabilities.isValidTransport(transport)) {
1381 throw new IllegalStateException("Unknown transport " + transport);
1382 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001383 switch (transport) {
1384 case TRANSPORT_WIFI:
1385 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1386 break;
1387 case TRANSPORT_CELLULAR:
1388 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1389 break;
1390 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001391 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001392 }
1393 // Test getNetworkInfo(Network)
1394 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001395 assertEquals(transportToLegacyType(transport),
1396 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001397 // Test getNetworkCapabilities(Network)
1398 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1399 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1400 }
1401
1402 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001403 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001404 // Test getActiveNetworkInfo()
1405 assertNull(mCm.getActiveNetworkInfo());
1406 // Test getActiveNetwork()
1407 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001408 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001409 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001410 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001411 }
1412
1413 /**
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001414 * Class to simplify expecting broadcasts using BroadcastInterceptingContext.
1415 * Ensures that the receiver is unregistered after the expected broadcast is received. This
1416 * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs
1417 * the receivers' receive method while iterating over the list of receivers, and unregistering
1418 * the receiver during iteration throws ConcurrentModificationException.
Paul Jensend7b6ca92015-05-13 14:05:12 -04001419 */
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001420 private class ExpectedBroadcast extends CompletableFuture<Intent> {
1421 private final BroadcastReceiver mReceiver;
1422
1423 ExpectedBroadcast(BroadcastReceiver receiver) {
1424 mReceiver = receiver;
1425 }
1426
1427 public Intent expectBroadcast(int timeoutMs) throws Exception {
1428 try {
1429 return get(timeoutMs, TimeUnit.MILLISECONDS);
1430 } catch (TimeoutException e) {
1431 fail("Expected broadcast not received after " + timeoutMs + " ms");
1432 return null;
1433 } finally {
1434 mServiceContext.unregisterReceiver(mReceiver);
1435 }
1436 }
1437
1438 public Intent expectBroadcast() throws Exception {
1439 return expectBroadcast(TIMEOUT_MS);
1440 }
1441
1442 public void expectNoBroadcast(int timeoutMs) throws Exception {
1443 waitForIdle();
1444 try {
1445 final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
1446 fail("Unexpected broadcast: " + intent.getAction());
1447 } catch (TimeoutException expected) {
1448 } finally {
1449 mServiceContext.unregisterReceiver(mReceiver);
1450 }
1451 }
1452 }
1453
1454 /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
1455 private ExpectedBroadcast registerConnectivityBroadcast(final int count) {
Chalard Jean407deb72019-11-19 16:14:30 +09001456 return registerConnectivityBroadcastThat(count, intent -> true);
Chalard Jean9ca13772019-11-15 12:08:36 +09001457 }
1458
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001459 private ExpectedBroadcast registerConnectivityBroadcastThat(final int count,
Chalard Jean9ca13772019-11-15 12:08:36 +09001460 @NonNull final Predicate<Intent> filter) {
Chalard Jean9ca13772019-11-15 12:08:36 +09001461 final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001462 // AtomicReference allows receiver to access expected even though it is constructed later.
1463 final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
Chalard Jean9ca13772019-11-15 12:08:36 +09001464 final BroadcastReceiver receiver = new BroadcastReceiver() {
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001465 private int mRemaining = count;
1466 public void onReceive(Context context, Intent intent) {
1467 final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
1468 final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
1469 Log.d(TAG, "Received CONNECTIVITY_ACTION type=" + type + " ni=" + ni);
1470 if (!filter.test(intent)) return;
1471 if (--mRemaining == 0) {
1472 expectedRef.get().complete(intent);
1473 }
1474 }
1475 };
1476 final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
1477 expectedRef.set(expected);
Chalard Jean9ca13772019-11-15 12:08:36 +09001478 mServiceContext.registerReceiver(receiver, intentFilter);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001479 return expected;
1480 }
1481
1482 private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
1483 return registerConnectivityBroadcastThat(1, intent ->
1484 type == intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) && state.equals(
1485 ((NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO))
1486 .getDetailedState()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001487 }
1488
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001489 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001490 public void testNetworkTypes() {
1491 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1492 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1493 // will fail. Failing here is much easier to debug.
1494 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1495 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001496 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1497 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1498
1499 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1500 // mocks, this assert exercises the ConnectivityService code path that ensures that
1501 // TYPE_ETHERNET is supported if the ethernet service is running.
1502 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001503 }
1504
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001505 @Test
Chalard Jean9ca13772019-11-15 12:08:36 +09001506 public void testNetworkFeature() throws Exception {
1507 // Connect the cell agent and wait for the connected broadcast.
1508 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1509 mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001510 ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
Chalard Jean9ca13772019-11-15 12:08:36 +09001511 mCellNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001512 b.expectBroadcast();
Chalard Jean9ca13772019-11-15 12:08:36 +09001513
1514 // Build legacy request for SUPL.
1515 final NetworkCapabilities legacyCaps = new NetworkCapabilities();
1516 legacyCaps.addTransportType(TRANSPORT_CELLULAR);
1517 legacyCaps.addCapability(NET_CAPABILITY_SUPL);
1518 final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
1519 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
1520
Automerger Merge Workerd40f64b2020-03-19 02:48:22 +00001521 // File request, withdraw it and make sure no broadcast is sent
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001522 b = registerConnectivityBroadcast(1);
Chalard Jean9ca13772019-11-15 12:08:36 +09001523 final TestNetworkCallback callback = new TestNetworkCallback();
Chalard Jean9ca13772019-11-15 12:08:36 +09001524 mCm.requestNetwork(legacyRequest, callback);
1525 callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
Automerger Merge Workerd40f64b2020-03-19 02:48:22 +00001526 mCm.unregisterNetworkCallback(callback);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001527 b.expectNoBroadcast(800); // 800ms long enough to at least flake if this is sent
Chalard Jean9ca13772019-11-15 12:08:36 +09001528
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001529 // Disconnect the network and expect mobile disconnected broadcast.
1530 b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
Chalard Jean9ca13772019-11-15 12:08:36 +09001531 mCellNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001532 b.expectBroadcast();
Chalard Jean9ca13772019-11-15 12:08:36 +09001533 }
1534
1535 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001536 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001537 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001538 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1539 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001540 assertNull(mCm.getActiveNetworkInfo());
1541 assertNull(mCm.getActiveNetwork());
1542 // Test bringing up validated cellular.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001543 ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001544 mCellNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001545 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001546 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001547 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001548 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1549 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1550 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1551 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1552 // Test bringing up validated WiFi.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001553 b = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001554 mWiFiNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001555 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001556 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001557 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001558 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1559 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1560 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1561 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1562 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001563 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001564 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001565 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001566 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001567 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001568 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1569 // Test WiFi disconnect.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001570 b = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001571 mWiFiNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001572 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001573 verifyNoNetwork();
1574 }
1575
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001576 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001577 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1578 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001579 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001580 ExpectedBroadcast b = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001581 mWiFiNetworkAgent.connect(false);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001582 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001583 verifyActiveNetwork(TRANSPORT_WIFI);
1584 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001585 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001586 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001587 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001588 verifyActiveNetwork(TRANSPORT_WIFI);
1589 // Test cellular disconnect.
1590 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001591 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001592 verifyActiveNetwork(TRANSPORT_WIFI);
1593 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001594 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001595 b = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001596 mCellNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001597 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001598 verifyActiveNetwork(TRANSPORT_CELLULAR);
1599 // Test cellular disconnect.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001600 b = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001601 mCellNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001602 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001603 verifyActiveNetwork(TRANSPORT_WIFI);
1604 // Test WiFi disconnect.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001605 b = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001606 mWiFiNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001607 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001608 verifyNoNetwork();
1609 }
1610
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001611 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001612 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1613 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001614 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001615 ExpectedBroadcast b = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001616 mCellNetworkAgent.connect(false);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001617 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001618 verifyActiveNetwork(TRANSPORT_CELLULAR);
1619 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001620 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001621 b = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001622 mWiFiNetworkAgent.connect(false);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001623 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001624 verifyActiveNetwork(TRANSPORT_WIFI);
1625 // Test WiFi disconnect.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001626 b = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001627 mWiFiNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001628 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001629 verifyActiveNetwork(TRANSPORT_CELLULAR);
1630 // Test cellular disconnect.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001631 b = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001632 mCellNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001633 b.expectBroadcast();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001634 verifyNoNetwork();
1635 }
1636
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001637 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001638 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001639 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001640 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001641 ExpectedBroadcast b = registerConnectivityBroadcast(1);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001642 mWiFiNetworkAgent.connect(false);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001643 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001644 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001645 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001646 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001647 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001648 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001649 b = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001650 mCellNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001651 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001652 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001653 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1654 NET_CAPABILITY_VALIDATED));
1655 // Test cellular disconnect.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001656 b = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001657 mCellNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001658 b.expectBroadcast();
Paul Jensencf4c2c62015-07-01 14:16:32 -04001659 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001660 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001661 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001662 NET_CAPABILITY_VALIDATED));
1663 }
1664
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001665 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001666 public void testCellularOutscoresWeakWifi() throws Exception {
1667 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001668 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001669 ExpectedBroadcast b = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001670 mCellNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001671 b.expectBroadcast();
Paul Jensen3d911462015-06-12 06:40:24 -04001672 verifyActiveNetwork(TRANSPORT_CELLULAR);
1673 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001674 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001675 b = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001676 mWiFiNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001677 b.expectBroadcast();
Paul Jensen3d911462015-06-12 06:40:24 -04001678 verifyActiveNetwork(TRANSPORT_WIFI);
1679 // Test WiFi getting really weak.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001680 b = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001681 mWiFiNetworkAgent.adjustScore(-11);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001682 b.expectBroadcast();
Paul Jensen3d911462015-06-12 06:40:24 -04001683 verifyActiveNetwork(TRANSPORT_CELLULAR);
1684 // Test WiFi restoring signal strength.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001685 b = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001686 mWiFiNetworkAgent.adjustScore(11);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001687 b.expectBroadcast();
Paul Jensen3d911462015-06-12 06:40:24 -04001688 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001689 }
1690
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001691 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001692 public void testReapingNetwork() throws Exception {
1693 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1694 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001695 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001696 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001697 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001698 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1699 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001700 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001701 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001702 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001703 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001704 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001705 final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
Paul Jensene0988542015-06-25 15:30:08 -04001706 mWiFiNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001707 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001708 verifyActiveNetwork(TRANSPORT_WIFI);
1709 // Test bringing up unvalidated cellular.
1710 // Expect it to be torn down because it could never be the highest scoring network
1711 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001712 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001713 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001714 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001715 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001716 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001717 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001718 }
1719
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001720 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001721 public void testCellularFallback() throws Exception {
1722 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001723 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001724 ExpectedBroadcast b = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001725 mCellNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001726 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001727 verifyActiveNetwork(TRANSPORT_CELLULAR);
1728 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001729 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001730 b = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001731 mWiFiNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001732 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001733 verifyActiveNetwork(TRANSPORT_WIFI);
1734 // Reevaluate WiFi (it'll instantly fail DNS).
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001735 b = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001736 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1737 NET_CAPABILITY_VALIDATED));
1738 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1739 // Should quickly fall back to Cellular.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001740 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001741 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1742 NET_CAPABILITY_VALIDATED));
1743 verifyActiveNetwork(TRANSPORT_CELLULAR);
1744 // Reevaluate cellular (it'll instantly fail DNS).
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001745 b = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001746 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1747 NET_CAPABILITY_VALIDATED));
1748 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1749 // Should quickly fall back to WiFi.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001750 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001751 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1752 NET_CAPABILITY_VALIDATED));
1753 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1754 NET_CAPABILITY_VALIDATED));
1755 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001756 }
1757
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001758 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001759 public void testWiFiFallback() throws Exception {
1760 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001761 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001762 ExpectedBroadcast b = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001763 mWiFiNetworkAgent.connect(false);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001764 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001765 verifyActiveNetwork(TRANSPORT_WIFI);
1766 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001767 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001768 b = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001769 mCellNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001770 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001771 verifyActiveNetwork(TRANSPORT_CELLULAR);
1772 // Reevaluate cellular (it'll instantly fail DNS).
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001773 b = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001774 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1775 NET_CAPABILITY_VALIDATED));
1776 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1777 // Should quickly fall back to WiFi.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001778 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04001779 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1780 NET_CAPABILITY_VALIDATED));
1781 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001782 }
1783
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001784 @Test
1785 public void testRequiresValidation() {
1786 assertTrue(NetworkMonitorUtils.isValidationRequired(
1787 mCm.getDefaultRequest().networkCapabilities));
1788 }
1789
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001790 /**
1791 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1792 * this class receives, by calling expectCallback() exactly once each time a callback is
1793 * received. assertNoCallback may be called at any time.
1794 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001795 private class TestNetworkCallback extends TestableNetworkCallback {
Chalard Jeanb299b842019-09-27 17:13:14 +09001796 TestNetworkCallback() {
1797 super(TEST_CALLBACK_TIMEOUT_MS);
1798 }
1799
Chalard Jean6f4216f2019-06-05 01:40:32 +09001800 @Override
1801 public void assertNoCallback() {
1802 // TODO: better support this use case in TestableNetworkCallback
1803 waitForIdle();
1804 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001805 }
Paul Jensen3d911462015-06-12 06:40:24 -04001806
Erik Klineacdd6392016-07-07 16:50:58 +09001807 @Override
Chalard Jean059c4262019-09-30 17:51:12 +09001808 public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
Chalard Jean6f4216f2019-06-05 01:40:32 +09001809 final long timeoutMs) {
1810 final T callback = super.expectCallback(type, n, timeoutMs);
Chalard Jean059c4262019-09-30 17:51:12 +09001811 if (callback instanceof CallbackEntry.Losing) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09001812 // TODO : move this to the specific test(s) needing this rather than here.
Chalard Jean059c4262019-09-30 17:51:12 +09001813 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001814 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001815 String msg = String.format(
1816 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001817 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001818 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001819 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001820 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001821 }
1822 }
1823
1824 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1825 // only be declared in a static or top level type".
1826 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1827 for (TestNetworkCallback c : callbacks) {
1828 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001829 }
1830 }
1831
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001832 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001833 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001834 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001835 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1836 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001837 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1838 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001839 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1840 .addTransportType(TRANSPORT_WIFI).build();
1841 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1842 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001843 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001844 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1845 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1846
1847 // Test unvalidated networks
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001848 ExpectedBroadcast b = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001849 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001850 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001851 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1852 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001853 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001854 b.expectBroadcast();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001855 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001856
Paul Jensen3d911462015-06-12 06:40:24 -04001857 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1858 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001859 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001860 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001861 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1862
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001863 b = registerConnectivityBroadcast(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001864 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001865 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001866 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1867 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001868 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001869 b.expectBroadcast();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001870 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001871
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001872 b = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001873 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001874 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1875 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001876 cellNetworkCallback.assertNoCallback();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001877 b.expectBroadcast();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001878 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001879
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001880 b = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001881 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001882 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1883 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09001884 b.expectBroadcast();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001885 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001886
1887 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001888 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001889 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001890 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1891 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001892 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001893 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001894
Paul Jensen3d911462015-06-12 06:40:24 -04001895 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1896 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001897 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001898 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001899 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1900
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001901 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001902 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001903 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001904 genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001905 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001906 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001907 cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001908 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001909 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001910
Paul Jensen3d911462015-06-12 06:40:24 -04001911 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001912 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1913 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001914 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001915
Paul Jensen3d911462015-06-12 06:40:24 -04001916 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001917 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1918 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001919 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001920 }
1921
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001922 private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
1923 final TestNetworkCallback callback = new TestNetworkCallback();
1924 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
1925 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1926 .addTransportType(TRANSPORT_WIFI).build();
1927 mCm.registerNetworkCallback(wifiRequest, callback);
1928 mCm.registerDefaultNetworkCallback(defaultCallback);
1929
1930 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1931 mWiFiNetworkAgent.connect(false);
1932 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1933 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1934
1935 final LinkProperties newLp = new LinkProperties();
1936 final Uri capportUrl = Uri.parse("https://capport.example.com/api");
1937 final CaptivePortalData capportData = new CaptivePortalData.Builder()
1938 .setCaptive(true).build();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001939
1940 final Uri expectedCapportUrl = sanitized ? null : capportUrl;
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001941 newLp.setCaptivePortalApiUrl(capportUrl);
1942 mWiFiNetworkAgent.sendLinkProperties(newLp);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001943 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001944 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001945 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001946 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
1947
1948 final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
1949 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(capportData);
1950 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1951 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
1952 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1953 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001954
1955 final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
1956 assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
1957 assertEquals(expectedCapportData, lp.getCaptivePortalData());
1958 }
1959
1960 @Test
1961 public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
1962 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1963 PERMISSION_DENIED);
1964 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
1965 PERMISSION_DENIED);
1966 doNetworkCallbacksSanitizationTest(true /* sanitized */);
1967 }
1968
1969 @Test
1970 public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
1971 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1972 PERMISSION_GRANTED);
1973 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
1974 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1975 }
1976
1977 @Test
1978 public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
1979 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1980 PERMISSION_DENIED);
1981 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
1982 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1983 }
1984
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001985 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001986 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001987 // This test would be flaky with the default 120ms timer: that is short enough that
1988 // lingered networks are torn down before assertions can be run. We don't want to mock the
1989 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1990 // in detecting races.
1991 mService.mLingerDelayMs = 300;
1992
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001993 NetworkRequest request = new NetworkRequest.Builder()
1994 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1995 .build();
1996 TestNetworkCallback callback = new TestNetworkCallback();
1997 mCm.registerNetworkCallback(request, callback);
1998
1999 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2000 mCm.registerDefaultNetworkCallback(defaultCallback);
2001
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002002 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2003 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2004 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002005
2006 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2007 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2008 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
2009
2010 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002011 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2012 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002013 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002014 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002015
2016 mWiFiNetworkAgent.connect(true);
2017 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
2018 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002019 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002020 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002021 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002022 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002023 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002024 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002025 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002026
2027 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002028 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002029 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002030 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002031 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002032 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002033 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002034 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002035
2036 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002037 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2038 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002039 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002040 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002041
2042 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002043 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002044 if (i % 2 == 0) {
2045 mWiFiNetworkAgent.adjustScore(-15);
2046 oldNetwork = mWiFiNetworkAgent;
2047 newNetwork = mCellNetworkAgent;
2048 } else {
2049 mWiFiNetworkAgent.adjustScore(15);
2050 oldNetwork = mCellNetworkAgent;
2051 newNetwork = mWiFiNetworkAgent;
2052
2053 }
Chalard Jean059c4262019-09-30 17:51:12 +09002054 callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002055 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
2056 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002057 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002058 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2059 }
2060 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2061
2062 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2063 // if the network is still up.
2064 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002065 // We expect a notification about the capabilities change, and nothing else.
2066 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2067 defaultCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09002068 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002069 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002070
2071 // Wifi no longer satisfies our listen, which is for an unmetered network.
2072 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002073 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2074
2075 // Disconnect our test networks.
2076 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002077 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002078 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002079 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002080 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002081 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002082 waitForIdle();
2083 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002084
2085 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002086 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002087
2088 // Check that a network is only lingered or torn down if it would not satisfy a request even
2089 // if it validated.
2090 request = new NetworkRequest.Builder().clearCapabilities().build();
2091 callback = new TestNetworkCallback();
2092
2093 mCm.registerNetworkCallback(request, callback);
2094
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002095 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002096 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002097 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2098 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002099 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002100 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002101
2102 // Bring up wifi with a score of 20.
2103 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002104 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002105 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002106 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2107 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002108 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002109 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002110
2111 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002112 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2113 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002114 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002115 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002116 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002117
Chalard Jeanfb830762020-02-20 07:32:12 +00002118 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002119 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002120 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanfb830762020-02-20 07:32:12 +00002121 mWiFiNetworkAgent.adjustScore(50);
2122 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002123 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002124 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jeanfb830762020-02-20 07:32:12 +00002125 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002126 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002127 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002128
2129 // Tear down wifi.
2130 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002131 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2132 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002133 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002134 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002135 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002136
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002137 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2138 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002139 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002140 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002141 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002142 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002143 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002144 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002145 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002146 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002147 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002148
2149 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002150 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2151 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002152 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002153 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002154 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2155 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002156 waitForIdle();
2157 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002158
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002159 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002160 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002161 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002162 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2163 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002164 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002165 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002166 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002167 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2168 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002169 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002170 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002171 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002172 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002173
2174 NetworkRequest cellRequest = new NetworkRequest.Builder()
2175 .addTransportType(TRANSPORT_CELLULAR).build();
2176 NetworkCallback noopCallback = new NetworkCallback();
2177 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002178 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2179 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002180 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002181 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002182
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002183 // Similar to the above: lingering can start even after the lingered request is removed.
2184 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002185 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002186 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2187 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002188 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002189 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002190
2191 // Cell is now the default network. Pin it with a cell-specific request.
2192 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2193 mCm.requestNetwork(cellRequest, noopCallback);
2194
2195 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002196 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002197 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002198 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2199 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002200 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002201 // The default request is lingering on cell, but nothing happens to cell, and we send no
2202 // callbacks for it, because it's kept up by cellRequest.
2203 callback.assertNoCallback();
2204 // Now unregister cellRequest and expect cell to start lingering.
2205 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002206 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002207
2208 // Let linger run its course.
2209 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002210 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09002211 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002212
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002213 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2214 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2215 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002216 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002217 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002218 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002219 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002220 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002221 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002222 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2223 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002224 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002225
2226 // Let linger run its course.
Chalard Jean059c4262019-09-30 17:51:12 +09002227 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002228
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002229 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002230 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002231 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2232 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2233 trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002234
2235 mCm.unregisterNetworkCallback(callback);
2236 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002237 mCm.unregisterNetworkCallback(trackDefaultCallback);
2238 }
2239
paulhu86e23eb2019-11-05 18:05:05 +08002240 private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
2241 final String testPackageName = mContext.getPackageName();
2242 when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
2243 .thenReturn(buildPackageInfo(true, uid));
2244 mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
2245 }
2246
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002247 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002248 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002249 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08002250 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Chalard Jean1fa777d2018-02-16 16:07:53 +09002251 NetworkRequest request = new NetworkRequest.Builder()
2252 .clearCapabilities()
2253 .build();
2254 TestNetworkCallback callback = new TestNetworkCallback();
2255 mCm.registerNetworkCallback(request, callback);
2256
2257 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2258 mCm.registerDefaultNetworkCallback(defaultCallback);
2259
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002260 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2261 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002262
2263 mCellNetworkAgent.connect(true);
2264 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2265 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2266
2267 // Wifi comes up and cell lingers.
2268 mWiFiNetworkAgent.connect(true);
2269 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2270 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002271 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002272 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2273
2274 // File a request for cellular, then release it.
2275 NetworkRequest cellRequest = new NetworkRequest.Builder()
2276 .addTransportType(TRANSPORT_CELLULAR).build();
2277 NetworkCallback noopCallback = new NetworkCallback();
2278 mCm.requestNetwork(cellRequest, noopCallback);
2279 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002280 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002281
2282 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002283 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002284 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2285 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2286 lingerTimeoutMs);
2287
2288 // Clean up.
2289 mCm.unregisterNetworkCallback(defaultCallback);
2290 mCm.unregisterNetworkCallback(callback);
2291 }
2292
2293 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002294 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002295 NetworkRequest request = new NetworkRequest.Builder()
2296 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2297 .build();
2298 TestNetworkCallback callback = new TestNetworkCallback();
2299 mCm.registerNetworkCallback(request, callback);
2300
2301 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002302 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002303 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002304 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002305
2306 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002307 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002308 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002309 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002310 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002311
2312 // Cell Remains the default.
2313 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2314
2315 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2316 // it's explicitly selected.
2317 mWiFiNetworkAgent.adjustScore(-40);
2318 mWiFiNetworkAgent.adjustScore(40);
2319 callback.assertNoCallback();
2320
2321 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2322 // wifi even though it's unvalidated.
2323 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002324 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002325 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2326
2327 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2328 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002329 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002330 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002331 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002332 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002333 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002334
2335 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2336 // network to disconnect.
2337 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002338 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002339
2340 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002341 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002342 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002343 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002344 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002345 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002346 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2347 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2348
2349 // BUG: the network will no longer linger, even though it's validated and outscored.
2350 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002351 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002352 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002353 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002354 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2355 callback.assertNoCallback();
2356
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002357 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
2358 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
2359 // wifi immediately.
2360 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002361 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002362 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002363 mWiFiNetworkAgent.explicitlySelected(true, true);
2364 mWiFiNetworkAgent.connect(false);
2365 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002366 callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002367 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2368 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002369 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002370
2371 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
2372 // Check that the network is not scored specially and that the device prefers cell data.
2373 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002374 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002375 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002376 mWiFiNetworkAgent.explicitlySelected(false, true);
2377 mWiFiNetworkAgent.connect(false);
2378 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2379 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2380
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002381 // Clean up.
2382 mWiFiNetworkAgent.disconnect();
2383 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002384
Chalard Jean059c4262019-09-30 17:51:12 +09002385 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2386 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002387 }
2388
Chalard Jean05ab6812018-05-02 21:14:54 +09002389 private int[] makeIntArray(final int size, final int value) {
2390 final int[] array = new int[size];
2391 Arrays.fill(array, value);
2392 return array;
2393 }
2394
Paul Jensen85cf78e2015-06-25 13:25:07 -04002395 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002396 // Verify NOT_RESTRICTED is set appropriately
2397 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2398 .build().networkCapabilities;
2399 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2400 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2401 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002402 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002403 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2404 } else {
2405 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2406 }
2407
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002408 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002409 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002410 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2411 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002412 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002413 mServiceContext, "testFactory", filter);
2414 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002415 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002416 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002417 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002418 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002419 int expectedRequestCount = 1;
2420 NetworkCallback networkCallback = null;
2421 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2422 // add one.
2423 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002424 assertFalse(testFactory.getMyStartRequested());
2425 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2426 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002427 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002428 mCm.requestNetwork(request, networkCallback);
2429 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002430 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002431 }
Paul Jensen3d911462015-06-12 06:40:24 -04002432 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002433 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2434 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002435
Paul Jensen85cf78e2015-06-25 13:25:07 -04002436 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002437 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002438 // Rather than create a validated network which complicates things by registering it's
2439 // own NetworkRequest during startup, just bump up the score to cancel out the
2440 // unvalidated penalty.
2441 testAgent.adjustScore(40);
2442 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002443
2444 // When testAgent connects, ConnectivityService will re-send us all current requests with
2445 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2446 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002447 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002448 testAgent.connect(false);
2449 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002450 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002451 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002452 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002453
Paul Jensen85cf78e2015-06-25 13:25:07 -04002454 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002455 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002456 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002457 ConnectivityManager.NetworkCallback[] networkCallbacks =
2458 new ConnectivityManager.NetworkCallback[10];
2459 for (int i = 0; i< networkCallbacks.length; i++) {
2460 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2461 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002462 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002463 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2464 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002465 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2466 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002467
Paul Jensen85cf78e2015-06-25 13:25:07 -04002468 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002469 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002470 for (int i = 0; i < networkCallbacks.length; i++) {
2471 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2472 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002473 testFactory.waitForNetworkRequests(expectedRequestCount);
2474 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002475
Paul Jensen85cf78e2015-06-25 13:25:07 -04002476 // Drop the higher scored network.
2477 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002478 // With the default network disconnecting, the requests are sent with score 0 to factories.
2479 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002480 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002481 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002482 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002483 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2484 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002485
Lorenzo Colittif1080a92020-03-02 19:46:35 +09002486 testFactory.terminate();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002487 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002488 handlerThread.quit();
2489 }
2490
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002491 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002492 public void testNetworkFactoryRequests() throws Exception {
2493 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2494 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2495 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2496 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2497 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2498 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2499 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2500 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2501 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2502 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2503 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2504 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2505 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2506 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2507 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2508 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2509 }
2510
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002511 @Test
Lorenzo Colittif1080a92020-03-02 19:46:35 +09002512 public void testNetworkFactoryUnregister() throws Exception {
2513 final NetworkCapabilities filter = new NetworkCapabilities();
2514 filter.clearAll();
2515
2516 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2517 handlerThread.start();
2518
2519 // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it
2520 // does not crash.
2521 for (int i = 0; i < 100; i++) {
2522 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2523 mServiceContext, "testFactory", filter);
2524 // Register the factory and don't be surprised when the default request arrives.
Lorenzo Colittif1080a92020-03-02 19:46:35 +09002525 testFactory.expectAddRequestsWithScores(0);
Junyu Lai2762be92020-03-18 10:01:45 +00002526 testFactory.register();
Lorenzo Colittif1080a92020-03-02 19:46:35 +09002527 testFactory.waitForNetworkRequests(1);
2528
2529 testFactory.setScoreFilter(42);
2530 testFactory.terminate();
2531
2532 if (i % 2 == 0) {
2533 try {
2534 testFactory.register();
2535 fail("Re-registering terminated NetworkFactory should throw");
2536 } catch (IllegalStateException expected) {
2537 }
2538 }
2539 }
2540 handlerThread.quit();
2541 }
2542
2543 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002544 public void testNoMutableNetworkRequests() throws Exception {
2545 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002546 NetworkRequest request1 = new NetworkRequest.Builder()
2547 .addCapability(NET_CAPABILITY_VALIDATED)
2548 .build();
2549 NetworkRequest request2 = new NetworkRequest.Builder()
2550 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2551 .build();
2552
2553 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002554 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2555 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2556 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2557 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002558 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002559
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002560 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002561 public void testMMSonWiFi() throws Exception {
2562 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002563 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002564 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002565 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002566 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002567 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002568 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002569 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002570
Paul Jensene0988542015-06-25 15:30:08 -04002571 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002572 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09002573 final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
Paul Jensene0988542015-06-25 15:30:08 -04002574 mWiFiNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09002575 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04002576 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002577
Paul Jensene0988542015-06-25 15:30:08 -04002578 // Register MMS NetworkRequest
2579 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2580 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2581 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2582 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002583
Paul Jensene0988542015-06-25 15:30:08 -04002584 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002585 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002586 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002587 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002588 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002589 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002590
Paul Jensene0988542015-06-25 15:30:08 -04002591 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002592 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002593 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002594 verifyActiveNetwork(TRANSPORT_WIFI);
2595 }
2596
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002597 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002598 public void testMMSonCell() throws Exception {
2599 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002600 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09002601 ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
Paul Jensene0988542015-06-25 15:30:08 -04002602 mCellNetworkAgent.connect(false);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09002603 b.expectBroadcast();
Paul Jensene0988542015-06-25 15:30:08 -04002604 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002605
Paul Jensene0988542015-06-25 15:30:08 -04002606 // Register MMS NetworkRequest
2607 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2608 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2609 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2610 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002611
Paul Jensene0988542015-06-25 15:30:08 -04002612 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002613 TestNetworkAgentWrapper
2614 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002615 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2616 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002617 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002618 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002619
Paul Jensene0988542015-06-25 15:30:08 -04002620 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002621 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002622 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002623 verifyActiveNetwork(TRANSPORT_CELLULAR);
2624 }
2625
lucaslinf3b59b32019-03-26 17:49:49 +08002626 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002627 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002628 // Register network callback.
2629 NetworkRequest request = new NetworkRequest.Builder()
2630 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2631 .build();
2632 TestNetworkCallback callback = new TestNetworkCallback();
2633 mCm.registerNetworkCallback(request, callback);
2634
2635 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002636 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002637 mCellNetworkAgent.connect(true);
2638 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2639
2640 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002641 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002642 mWiFiNetworkAgent.connectWithPartialConnectivity();
2643 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2644 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2645
2646 // Mobile data should be the default network.
2647 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2648 callback.assertNoCallback();
2649
lucaslinf3b59b32019-03-26 17:49:49 +08002650 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2651 // probe.
lucaslin783f2212019-10-22 18:27:33 +08002652 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
lucasline252a742019-03-12 13:08:03 +08002653 // If the user chooses yes to use this partial connectivity wifi, switch the default
2654 // network to wifi and check if wifi becomes valid or not.
2655 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2656 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002657 // If user accepts partial connectivity network,
2658 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002659 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002660 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002661
lucaslinf3b59b32019-03-26 17:49:49 +08002662 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2663 // validated.
2664 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002665 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002666 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2667 mWiFiNetworkAgent);
2668 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2669 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2670
2671 // Disconnect and reconnect wifi with partial connectivity again.
2672 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002673 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002674 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002675 mWiFiNetworkAgent.connectWithPartialConnectivity();
2676 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2677 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2678
2679 // Mobile data should be the default network.
2680 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2681
2682 // If the user chooses no, disconnect wifi immediately.
2683 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2684 false /* always */);
Chalard Jean059c4262019-09-30 17:51:12 +09002685 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002686
2687 // If user accepted partial connectivity before, and device reconnects to that network
2688 // again, but now the network has full connectivity. The network shouldn't contain
2689 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002690 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002691 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002692 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2693 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002694 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002695
lucaslinf3b59b32019-03-26 17:49:49 +08002696 // If user accepted partial connectivity network before,
2697 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2698 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002699 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002700 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002701 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002702 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2703 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002704
lucasline252a742019-03-12 13:08:03 +08002705 // Wifi should be the default network.
2706 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2707 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002708 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002709
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002710 // The user accepted partial connectivity and selected "don't ask again". Now the user
2711 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2712 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002713 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002714 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2715 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002716 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002717 // If user accepted partial connectivity network before,
2718 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2719 // ConnectivityService#updateNetworkInfo().
lucaslinf3b59b32019-03-26 17:49:49 +08002720 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002721 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002722 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002723 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002724 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
lucaslin783f2212019-10-22 18:27:33 +08002725 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002726
lucaslinf3b59b32019-03-26 17:49:49 +08002727 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2728 // validated.
2729 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2730 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2731 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002732 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002733
2734 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2735 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002736 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002737 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2738 true /* acceptUnvalidated */);
2739
2740 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2741 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2742 // notifyNetworkConnected.
lucaslin783f2212019-10-22 18:27:33 +08002743 mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002744 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002745 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002746 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002747 callback.expectCapabilitiesWith(
2748 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2749 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002750 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002751 }
2752
2753 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002754 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002755 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2756 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2757 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2758 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2759
2760 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2761 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2762 .addCapability(NET_CAPABILITY_VALIDATED).build();
2763 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2764
2765 // Bring up a network with a captive portal.
2766 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002767 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002768 String redirectUrl = "http://android.com/path";
lucaslin783f2212019-10-22 18:27:33 +08002769 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002770 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002771 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002772
2773 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2774 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2775 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2776 .launchCaptivePortalApp();
2777
2778 // Report that the captive portal is dismissed with partial connectivity, and check that
2779 // callbacks are fired.
2780 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002781 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002782 waitForIdle();
2783 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2784 mWiFiNetworkAgent);
2785
2786 // Report partial connectivity is accepted.
lucaslin783f2212019-10-22 18:27:33 +08002787 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002788 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2789 false /* always */);
2790 waitForIdle();
2791 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002792 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002793 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2794 NetworkCapabilities nc =
2795 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2796 mWiFiNetworkAgent);
2797
2798 mCm.unregisterNetworkCallback(captivePortalCallback);
2799 mCm.unregisterNetworkCallback(validatedCallback);
2800 }
2801
2802 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002803 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002804 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2805 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2806 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2807 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2808
2809 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2810 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2811 .addCapability(NET_CAPABILITY_VALIDATED).build();
2812 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002813
2814 // Bring up a network with a captive portal.
2815 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002816 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002817 String firstRedirectUrl = "http://example.com/firstPath";
lucaslin783f2212019-10-22 18:27:33 +08002818 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002819 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002820 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002821
2822 // Take down network.
2823 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002824 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002825 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002826
2827 // Bring up a network with a captive portal.
2828 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002829 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002830 String secondRedirectUrl = "http://example.com/secondPath";
lucaslin783f2212019-10-22 18:27:33 +08002831 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002832 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002833 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002834
2835 // Make captive portal disappear then revalidate.
2836 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
lucaslin783f2212019-10-22 18:27:33 +08002837 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002838 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002839 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002840
2841 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002842 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002843
2844 // Break network connectivity.
2845 // Expect NET_CAPABILITY_VALIDATED onLost callback.
lucaslin783f2212019-10-22 18:27:33 +08002846 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002847 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean059c4262019-09-30 17:51:12 +09002848 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002849 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002850
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002851 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002852 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002853 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2854 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2855 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2856 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2857
2858 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2859 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2860 .addCapability(NET_CAPABILITY_VALIDATED).build();
2861 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2862
2863 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002864 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002865 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002866 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002867 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2868
2869 // Check that calling startCaptivePortalApp does nothing.
2870 final int fastTimeoutMs = 100;
2871 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002872 waitForIdle();
2873 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002874 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2875
2876 // Turn into a captive portal.
lucaslin783f2212019-10-22 18:27:33 +08002877 mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002878 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002879 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002880 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002881
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002882 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002883 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002884 waitForIdle();
2885 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2886
2887 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2888 final Bundle testBundle = new Bundle();
2889 final String testKey = "testkey";
2890 final String testValue = "testvalue";
2891 testBundle.putString(testKey, testValue);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09002892 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2893 PERMISSION_GRANTED);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002894 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2895 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2896 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2897 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002898
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002899 // Report that the captive portal is dismissed, and check that callbacks are fired
lucaslin783f2212019-10-22 18:27:33 +08002900 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002901 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002902 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002903 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002904
2905 mCm.unregisterNetworkCallback(validatedCallback);
2906 mCm.unregisterNetworkCallback(captivePortalCallback);
2907 }
2908
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002909 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002910 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002911 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2912 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2913 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2914 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2915
2916 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2917 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2918 .addCapability(NET_CAPABILITY_VALIDATED).build();
2919 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2920
2921 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2922 // Bring up a network with a captive portal.
2923 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002924 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002925 String firstRedirectUrl = "http://example.com/firstPath";
2926
lucaslin783f2212019-10-22 18:27:33 +08002927 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002928 mWiFiNetworkAgent.expectDisconnected();
2929 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002930
2931 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002932 }
2933
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09002934 @Test
2935 public void testCaptivePortalApi() throws Exception {
2936 mServiceContext.setPermission(
2937 android.Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
2938
2939 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2940 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2941 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2942 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2943
2944 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2945 final String redirectUrl = "http://example.com/firstPath";
2946
2947 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
2948 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2949
2950 final CaptivePortalData testData = new CaptivePortalData.Builder()
2951 .setUserPortalUrl(Uri.parse(redirectUrl))
2952 .setBytesRemaining(12345L)
2953 .build();
2954
2955 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(testData);
2956
2957 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
2958 lp -> testData.equals(lp.getCaptivePortalData()));
2959
2960 final LinkProperties newLps = new LinkProperties();
2961 newLps.setMtu(1234);
2962 mWiFiNetworkAgent.sendLinkProperties(newLps);
2963 // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
2964 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
2965 lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
2966 }
2967
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002968 private NetworkRequest.Builder newWifiRequestBuilder() {
2969 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2970 }
2971
Etan Cohen836ad572018-12-30 17:59:59 -08002972 /**
2973 * Verify request matching behavior with network specifiers.
2974 *
2975 * Note: this test is somewhat problematic since it involves removing capabilities from
2976 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2977 * as a WTF bug in
2978 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2979 * does work.
2980 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002981 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002982 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002983 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2984 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2985 Parcelable {
2986 @Override
Chalard Jean2da4f9f2020-03-27 17:57:34 +09002987 public boolean canBeSatisfiedBy(NetworkSpecifier other) {
Etan Cohen836ad572018-12-30 17:59:59 -08002988 return true;
2989 }
2990
2991 @Override
2992 public int describeContents() {
2993 return 0;
2994 }
2995
2996 @Override
2997 public void writeToParcel(Parcel dest, int flags) {}
2998
2999 @Override
3000 public NetworkSpecifier redact() {
3001 return null;
3002 }
3003 }
3004
3005 // A network specifier that matches either another LocalNetworkSpecifier with the same
3006 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
3007 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
3008 private String mString;
3009
3010 LocalStringNetworkSpecifier(String string) {
3011 mString = string;
3012 }
3013
3014 @Override
Chalard Jean2da4f9f2020-03-27 17:57:34 +09003015 public boolean canBeSatisfiedBy(NetworkSpecifier other) {
Etan Cohen836ad572018-12-30 17:59:59 -08003016 if (other instanceof LocalStringNetworkSpecifier) {
3017 return TextUtils.equals(mString,
3018 ((LocalStringNetworkSpecifier) other).mString);
3019 }
3020 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
3021 return false;
3022 }
3023
3024 @Override
3025 public int describeContents() {
3026 return 0;
3027 }
3028 @Override
3029 public void writeToParcel(Parcel dest, int flags) {}
3030 }
3031
3032
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003033 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07003034 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003035 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07003036 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
3037 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08003038 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
3039 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07003040 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08003041 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003042
3043 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
3044 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
3045 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07003046 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003047 TestNetworkCallback cFoo = new TestNetworkCallback();
3048 TestNetworkCallback cBar = new TestNetworkCallback();
3049 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08003050 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003051
3052 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
3053 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
3054 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07003055 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003056 mCm.registerNetworkCallback(rFoo, cFoo);
3057 mCm.registerNetworkCallback(rBar, cBar);
3058
Etan Cohen836ad572018-12-30 17:59:59 -08003059 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
3060 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
3061
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003062 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003063 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003064 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3065 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3066 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3067 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003068 assertNoCallbacks(cFoo, cBar);
3069
Etan Cohen836ad572018-12-30 17:59:59 -08003070 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003071 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003072 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003073 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3074 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003075 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003076 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
3077 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08003078 assertEquals(nsFoo,
3079 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003080 cFoo.assertNoCallback();
3081
Etan Cohen836ad572018-12-30 17:59:59 -08003082 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean059c4262019-09-30 17:51:12 +09003083 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003084 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003085 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003086 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3087 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003088 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003089 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
3090 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08003091 assertEquals(nsBar,
3092 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3093 cBar.assertNoCallback();
3094
3095 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
3096 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3097 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003098 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3099 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08003100 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003101 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
3102 (caps) -> caps.getNetworkSpecifier() == null);
3103 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
3104 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08003105 assertNull(
3106 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3107 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003108 cBar.assertNoCallback();
3109
3110 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean059c4262019-09-30 17:51:12 +09003111 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3112 cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003113 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean059c4262019-09-30 17:51:12 +09003114 c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003115 }
3116
Etan Cohen836ad572018-12-30 17:59:59 -08003117 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003118 }
3119
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003120 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08003121 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09003122 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003123 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07003124 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003125 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003126
Chalard Jean751bb3f2019-06-19 23:29:58 +09003127 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003128 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3129 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07003130 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08003131 mService.requestNetwork(networkCapabilities, null, 0, null,
Qingxi Li9c5d8b92020-01-08 12:51:49 -08003132 ConnectivityManager.TYPE_WIFI, mContext.getPackageName());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003133 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003134
Etan Cohena7434272017-04-03 12:17:51 -07003135 class NonParcelableSpecifier extends NetworkSpecifier {
Chalard Jean2da4f9f2020-03-27 17:57:34 +09003136 @Override
3137 public boolean canBeSatisfiedBy(NetworkSpecifier other) {
3138 return false;
3139 }
Etan Cohena7434272017-04-03 12:17:51 -07003140 };
3141 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3142 @Override public int describeContents() { return 0; }
3143 @Override public void writeToParcel(Parcel p, int flags) {}
3144 }
Etan Cohena7434272017-04-03 12:17:51 -07003145
Chalard Jean751bb3f2019-06-19 23:29:58 +09003146 final NetworkRequest.Builder builder =
3147 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3148 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07003149 builder.setNetworkSpecifier(new NonParcelableSpecifier());
3150 Parcel parcelW = Parcel.obtain();
3151 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003152 });
Etan Cohena7434272017-04-03 12:17:51 -07003153
Chalard Jean751bb3f2019-06-19 23:29:58 +09003154 final NetworkRequest nr =
3155 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
3156 .setNetworkSpecifier(new ParcelableSpecifier())
3157 .build();
Etan Cohena7434272017-04-03 12:17:51 -07003158 assertNotNull(nr);
3159
Chalard Jean751bb3f2019-06-19 23:29:58 +09003160 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07003161 Parcel parcelW = Parcel.obtain();
3162 nr.writeToParcel(parcelW, 0);
3163 byte[] bytes = parcelW.marshall();
3164 parcelW.recycle();
3165
3166 Parcel parcelR = Parcel.obtain();
3167 parcelR.unmarshall(bytes, 0, bytes.length);
3168 parcelR.setDataPosition(0);
3169 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003170 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003171 }
3172
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003173 @Test
Roshan Piuse38acab2020-01-16 12:17:17 -08003174 public void testNetworkRequestUidSpoofSecurityException() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003175 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07003176 mWiFiNetworkAgent.connect(false);
Roshan Piuse38acab2020-01-16 12:17:17 -08003177 NetworkRequest networkRequest = newWifiRequestBuilder().build();
Etan Cohen859748f2017-04-03 17:42:34 -07003178 TestNetworkCallback networkCallback = new TestNetworkCallback();
Roshan Piuse38acab2020-01-16 12:17:17 -08003179 doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003180 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07003181 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003182 });
Etan Cohen859748f2017-04-03 17:42:34 -07003183 }
3184
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003185 @Test
paulhu3d67f532019-03-22 16:35:06 +08003186 public void testInvalidSignalStrength() {
3187 NetworkRequest r = new NetworkRequest.Builder()
3188 .addCapability(NET_CAPABILITY_INTERNET)
3189 .addTransportType(TRANSPORT_WIFI)
3190 .setSignalStrength(-75)
3191 .build();
3192 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3193 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003194 assertThrows(SecurityException.class, () ->
3195 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003196
Chalard Jean751bb3f2019-06-19 23:29:58 +09003197 assertThrows(SecurityException.class, () ->
3198 mCm.registerNetworkCallback(r, PendingIntent.getService(
3199 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003200
3201 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003202 assertThrows(IllegalArgumentException.class, () ->
3203 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003204
Chalard Jean751bb3f2019-06-19 23:29:58 +09003205 assertThrows(IllegalArgumentException.class, () ->
3206 mCm.requestNetwork(r, PendingIntent.getService(
3207 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003208 }
3209
3210 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003211 public void testRegisterDefaultNetworkCallback() throws Exception {
3212 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3213 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3214 defaultNetworkCallback.assertNoCallback();
3215
3216 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3217 // whenever Wi-Fi is up. Without this, the mobile network agent is
3218 // reaped before any other activity can take place.
3219 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3220 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3221 .addTransportType(TRANSPORT_CELLULAR).build();
3222 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3223 cellNetworkCallback.assertNoCallback();
3224
3225 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003226 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003227 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003228 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3229 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003230 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003231
3232 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003233 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09003234 mWiFiNetworkAgent.connect(true);
3235 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003236 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003237 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003238
3239 // Bring down cell. Expect no default network callback, since it wasn't the default.
3240 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003241 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003242 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003243 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003244
3245 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003246 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003247 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003248 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003249 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003250 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003251
3252 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3253 // followed by AVAILABLE cell.
3254 mWiFiNetworkAgent.disconnect();
3255 cellNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09003256 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003257 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003258 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003259 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3260 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003261 waitForIdle();
3262 assertEquals(null, mCm.getActiveNetwork());
3263
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09003264 mMockVpn.establishForMyUid();
3265 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003266 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3267
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09003268 mMockVpn.disconnect();
3269 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003270 waitForIdle();
3271 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003272 }
3273
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003274 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003275 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003276 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003277 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003278 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3279 .addTransportType(TRANSPORT_CELLULAR).build();
3280 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3281
3282 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003283 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09003284 mCellNetworkAgent.connect(true);
3285
Erik Kline1d3db322017-02-28 16:20:20 +09003286 // We should get onAvailable(), onCapabilitiesChanged(), and
3287 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3288 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003289 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003290 cellNetworkCallback.assertNoCallback();
3291
3292 // Update LinkProperties.
3293 final LinkProperties lp = new LinkProperties();
3294 lp.setInterfaceName("foonet_data0");
3295 mCellNetworkAgent.sendLinkProperties(lp);
3296 // We should get onLinkPropertiesChanged().
Chalard Jean059c4262019-09-30 17:51:12 +09003297 cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Chalard Jean6f4216f2019-06-05 01:40:32 +09003298 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003299 cellNetworkCallback.assertNoCallback();
3300
Erik Kline1d3db322017-02-28 16:20:20 +09003301 // Suspend the network.
3302 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003303 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3304 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003305 cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003306 cellNetworkCallback.assertNoCallback();
Chiachang Wanga5d8fe82020-02-12 17:01:59 +08003307 assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
Erik Kline1d3db322017-02-28 16:20:20 +09003308
Erik Klineacdd6392016-07-07 16:50:58 +09003309 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003310 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003311 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003312 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3313 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003314 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003315 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003316 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3317
3318 mCellNetworkAgent.resume();
3319 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3320 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003321 cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09003322 cellNetworkCallback.assertNoCallback();
Chiachang Wanga5d8fe82020-02-12 17:01:59 +08003323 assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
Chalard Jean804b8fb2018-01-30 22:41:41 +09003324
3325 dfltNetworkCallback = new TestNetworkCallback();
3326 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3327 // This time onNetworkSuspended should not be called.
3328 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3329 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003330
Erik Klineacdd6392016-07-07 16:50:58 +09003331 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3332 mCm.unregisterNetworkCallback(cellNetworkCallback);
3333 }
3334
Calvin On1f64f3f2016-10-11 15:10:46 -07003335 private void setCaptivePortalMode(int mode) {
3336 ContentResolver cr = mServiceContext.getContentResolver();
3337 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3338 }
3339
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003340 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003341 ContentResolver cr = mServiceContext.getContentResolver();
3342 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003343 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003344 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003345 }
3346
Erik Kline79c6d052018-03-21 07:18:33 -07003347 private void setPrivateDnsSettings(String mode, String specifier) {
3348 final ContentResolver cr = mServiceContext.getContentResolver();
3349 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3350 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3351 mService.updatePrivateDnsSettings();
3352 waitForIdle();
3353 }
3354
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003355 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003356 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3357 assertNotNull(nc);
3358 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3359 }
3360
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003361 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003362 public void testBackgroundNetworks() throws Exception {
3363 // Create a background request. We can't do this ourselves because ConnectivityService
3364 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003365 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08003366 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003367 final NetworkRequest request = new NetworkRequest.Builder().build();
3368 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3369 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3370 final TestNetworkCallback callback = new TestNetworkCallback();
3371 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3372 mCm.registerNetworkCallback(request, callback);
3373 mCm.registerNetworkCallback(fgRequest, fgCallback);
3374
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003375 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003376 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003377 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3378 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003379 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3380
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003381 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003382 mWiFiNetworkAgent.connect(true);
3383
3384 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003385 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003386 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003387 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003388 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003389 fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003390 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003391 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3392 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3393
3394 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003395 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003396 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09003397 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003398 // Expect a network capabilities update sans FOREGROUND.
3399 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003400 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3401 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3402
3403 // File a cell request and check that cell comes into the foreground.
3404 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3405 .addTransportType(TRANSPORT_CELLULAR).build();
3406 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3407 mCm.requestNetwork(cellRequest, cellCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003408 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3409 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003410 // Expect a network capabilities update with FOREGROUND, because the most recent
3411 // request causes its state to change.
Chalard Jean28e6b262019-11-19 21:30:44 +09003412 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003413 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003414 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3415 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3416
3417 // Release the request. The network immediately goes into the background, since it was not
3418 // lingering.
3419 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09003420 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003421 // Expect a network capabilities update sans FOREGROUND.
3422 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003423 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3424 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3425
3426 // Disconnect wifi and check that cell is foreground again.
3427 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003428 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3429 fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003430 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003431 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3432
3433 mCm.unregisterNetworkCallback(callback);
3434 mCm.unregisterNetworkCallback(fgCallback);
3435 }
3436
Hugo Benichi849b81b2017-05-25 13:42:31 +09003437 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003438 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003439 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003440 // Benchmarks connecting and switching performance in the presence of a large number of
3441 // NetworkRequests.
3442 // 1. File NUM_REQUESTS requests.
3443 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3444 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3445 // and NUM_REQUESTS onAvailable callbacks to fire.
3446 // See how long it took.
3447 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003448 final int REGISTER_TIME_LIMIT_MS = 200;
3449 final int CONNECT_TIME_LIMIT_MS = 60;
3450 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003451 final int UNREGISTER_TIME_LIMIT_MS = 20;
3452
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003453 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3454 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3455 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3456 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3457
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003458 for (int i = 0; i < NUM_REQUESTS; i++) {
3459 callbacks[i] = new NetworkCallback() {
3460 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3461 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3462 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003463 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003464
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003465 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003466 for (NetworkCallback cb : callbacks) {
3467 mCm.registerNetworkCallback(request, cb);
3468 }
3469 });
3470
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003471 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003472 // Don't request that the network validate, because otherwise connect() will block until
3473 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3474 // and we won't actually measure anything.
3475 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003476
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003477 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003478 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003479 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003480 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3481 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3482 onAvailableDispatchingDuration));
3483 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3484 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3485 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003486
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003487 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003488 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003489 mWiFiNetworkAgent.adjustScore(40);
3490 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003491
3492 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003493 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003494 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003495 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3496 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3497 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3498 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3499 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003500
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003501 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003502 for (NetworkCallback cb : callbacks) {
3503 mCm.unregisterNetworkCallback(cb);
3504 }
3505 });
3506 }
3507
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003508 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003509 public void testMobileDataAlwaysOn() throws Exception {
paulhu86e23eb2019-11-05 18:05:05 +08003510 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003511 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3512 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3513 .addTransportType(TRANSPORT_CELLULAR).build();
3514 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3515
3516 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3517 handlerThread.start();
3518 NetworkCapabilities filter = new NetworkCapabilities()
3519 .addTransportType(TRANSPORT_CELLULAR)
3520 .addCapability(NET_CAPABILITY_INTERNET);
3521 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3522 mServiceContext, "testFactory", filter);
3523 testFactory.setScoreFilter(40);
3524
3525 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003526 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003527 testFactory.register();
3528 testFactory.waitForNetworkRequests(1);
3529 assertTrue(testFactory.getMyStartRequested());
3530
3531 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003532 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003533 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3534 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003535 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003536 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003537 assertFalse(testFactory.getMyStartRequested());
3538
3539 ContentResolver cr = mServiceContext.getContentResolver();
3540
3541 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003542 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003543 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003544 testFactory.waitForNetworkRequests(2);
3545 assertTrue(testFactory.getMyStartRequested());
3546
3547 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003548 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003549 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003550 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003551 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003552 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003553 testFactory.waitForNetworkRequests(2);
3554 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3555
3556 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003557 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003558 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003559 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003560
3561 // Turn off mobile data always on and expect the request to disappear...
3562 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003563 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003564 testFactory.waitForNetworkRequests(1);
3565
3566 // ... and cell data to be torn down.
Chalard Jean059c4262019-09-30 17:51:12 +09003567 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003568 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003569
Lorenzo Colittif1080a92020-03-02 19:46:35 +09003570 testFactory.terminate();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003571 mCm.unregisterNetworkCallback(cellNetworkCallback);
3572 handlerThread.quit();
3573 }
3574
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003575 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003576 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003577 final ContentResolver cr = mServiceContext.getContentResolver();
3578 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3579
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003580 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003581 String[] values = new String[] {null, "0", "1"};
3582 for (int i = 0; i < values.length; i++) {
3583 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003584 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003585 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003586 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003587 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003588 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003589 }
3590
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003591 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003592
3593 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003594 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003595 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003596 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003597 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003598
3599 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003600 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003601 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003602 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003603 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003604
3605 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003606 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003607 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003608 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003609 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003610 }
3611
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003612 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003613 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003614 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003615
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003616 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003617 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003618
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003619 // File a request for cell to ensure it doesn't go down.
3620 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3621 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3622 .addTransportType(TRANSPORT_CELLULAR).build();
3623 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3624
3625 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3626 mCm.registerDefaultNetworkCallback(defaultCallback);
3627
3628 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3629 .addTransportType(TRANSPORT_WIFI)
3630 .addCapability(NET_CAPABILITY_VALIDATED)
3631 .build();
3632 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3633 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3634
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003635 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003636 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003637
3638 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003639 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003640 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003641 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3642 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003643 Network cellNetwork = mCellNetworkAgent.getNetwork();
3644
3645 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003646 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003647 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003648 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3649 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003650 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3651
3652 // Fail validation on wifi.
lucaslin783f2212019-10-22 18:27:33 +08003653 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003654 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003655 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003656 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003657
3658 // Because avoid bad wifi is off, we don't switch to cellular.
3659 defaultCallback.assertNoCallback();
3660 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3661 NET_CAPABILITY_VALIDATED));
3662 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3663 NET_CAPABILITY_VALIDATED));
3664 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3665
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003666 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3667 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003668 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3669 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003670 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003671 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3672
3673 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003674 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3675 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003676 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003677 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3678
3679 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3680 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003681 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003682 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3683 NET_CAPABILITY_VALIDATED));
3684 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3685 NET_CAPABILITY_VALIDATED));
3686 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3687
3688 // Disconnect and reconnect wifi to clear the one-time switch above.
3689 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003690 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003691 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003692 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3693 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003694 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3695
3696 // Fail validation on wifi and expect the dialog to appear.
lucaslin783f2212019-10-22 18:27:33 +08003697 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003698 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003699 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003700 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003701
3702 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003703 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003704 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003705
3706 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003707 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003708 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3709 NET_CAPABILITY_VALIDATED));
3710 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3711 NET_CAPABILITY_VALIDATED));
3712 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3713
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003714 // Simulate the user turning the cellular fallback setting off and then on.
3715 // We switch to wifi and then to cell.
3716 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003717 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003718 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003719 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3720 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003721 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003722 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003723 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3724
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003725 // If cell goes down, we switch to wifi.
3726 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003727 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003728 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003729 validatedWifiCallback.assertNoCallback();
3730
3731 mCm.unregisterNetworkCallback(cellNetworkCallback);
3732 mCm.unregisterNetworkCallback(validatedWifiCallback);
3733 mCm.unregisterNetworkCallback(defaultCallback);
3734 }
3735
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003736 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003737 public void testMeteredMultipathPreferenceSetting() throws Exception {
3738 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003739 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3740
3741 for (int config : Arrays.asList(0, 3, 2)) {
3742 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003743 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003744 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003745 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003746 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003747
3748 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3749 String msg = String.format("config=%d, setting=%s", config, setting);
3750 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3751 }
3752 }
3753 }
3754
Erik Kline3841a482015-11-25 12:49:38 +09003755 /**
3756 * Validate that a satisfied network request does not trigger onUnavailable() once the
3757 * time-out period expires.
3758 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003759 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003760 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003761 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3762 NetworkCapabilities.TRANSPORT_WIFI).build();
3763 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003764 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003765
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003766 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003767 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003768 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003769 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003770
3771 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003772 networkCallback.assertNoCallback();
3773 }
3774
3775 /**
3776 * Validate that a satisfied network request followed by a disconnected (lost) network does
3777 * not trigger onUnavailable() once the time-out period expires.
3778 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003779 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003780 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003781 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3782 NetworkCapabilities.TRANSPORT_WIFI).build();
3783 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003784 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003785
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003786 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003787 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003788 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003789 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003790 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003791 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003792
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003793 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003794 networkCallback.assertNoCallback();
3795 }
3796
3797 /**
3798 * Validate that when a time-out is specified for a network request the onUnavailable()
3799 * callback is called when time-out expires. Then validate that if network request is
3800 * (somehow) satisfied - the callback isn't called later.
3801 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003802 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003803 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003804 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3805 NetworkCapabilities.TRANSPORT_WIFI).build();
3806 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003807 final int timeoutMs = 10;
3808 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003809
3810 // pass timeout and validate that UNAVAILABLE is called
Automerger Merge Worker6b606b32020-03-14 05:13:42 +00003811 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
Erik Kline3841a482015-11-25 12:49:38 +09003812
3813 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003814 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003815 mWiFiNetworkAgent.connect(false);
3816 networkCallback.assertNoCallback();
3817 }
3818
3819 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003820 * Validate that when a network request is unregistered (cancelled), no posterior event can
3821 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003822 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003823 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003824 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003825 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3826 NetworkCapabilities.TRANSPORT_WIFI).build();
3827 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003828 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003829
Hugo Benichidfb559a2016-12-20 14:57:49 +09003830 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003831 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003832 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3833 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003834 networkCallback.assertNoCallback();
3835
3836 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003837 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003838 mWiFiNetworkAgent.connect(false);
3839 networkCallback.assertNoCallback();
3840 }
3841
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003842 @Test
3843 public void testUnfulfillableNetworkRequest() throws Exception {
3844 runUnfulfillableNetworkRequest(false);
3845 }
3846
3847 @Test
3848 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3849 runUnfulfillableNetworkRequest(true);
3850 }
3851
Etan Cohenddb720a2019-01-08 12:09:18 -08003852 /**
3853 * Validate the callback flow for a factory releasing a request as unfulfillable.
3854 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003855 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003856 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3857 NetworkCapabilities.TRANSPORT_WIFI).build();
3858 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3859
3860 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3861 handlerThread.start();
3862 NetworkCapabilities filter = new NetworkCapabilities()
3863 .addTransportType(TRANSPORT_WIFI)
3864 .addCapability(NET_CAPABILITY_INTERNET);
3865 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3866 mServiceContext, "testFactory", filter);
3867 testFactory.setScoreFilter(40);
3868
3869 // Register the factory and expect it to receive the default request.
Etan Cohenae574a82019-01-08 12:09:18 -08003870 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003871 testFactory.register();
3872 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3873
3874 assertEquals(1, requests.size()); // have 1 request at this point
3875 int origRequestId = requests.valueAt(0).requestId;
3876
3877 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003878 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003879 mCm.requestNetwork(nr, networkCallback);
3880 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3881
3882 int newRequestId = 0;
3883 for (int i = 0; i < requests.size(); ++i) {
3884 if (requests.valueAt(i).requestId != origRequestId) {
3885 newRequestId = requests.valueAt(i).requestId;
3886 break;
3887 }
3888 }
3889
Etan Cohen22e0fc12019-05-23 08:16:20 -07003890 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003891 if (preUnregister) {
3892 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003893
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003894 // Simulate the factory releasing the request as unfulfillable: no-op since
3895 // the callback has already been unregistered (but a test that no exceptions are
3896 // thrown).
3897 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3898 } else {
3899 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003900 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3901
Automerger Merge Worker6b606b32020-03-14 05:13:42 +00003902 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003903 testFactory.waitForRequests();
3904
3905 // unregister network callback - a no-op (since already freed by the
3906 // on-unavailable), but should not fail or throw exceptions.
3907 mCm.unregisterNetworkCallback(networkCallback);
3908 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003909
Lorenzo Colittif1080a92020-03-02 19:46:35 +09003910 testFactory.terminate();
Etan Cohenddb720a2019-01-08 12:09:18 -08003911 handlerThread.quit();
3912 }
3913
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003914 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3915
Chalard Jeane7b24752019-06-20 16:01:19 +09003916 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003917
3918 private class CallbackValue {
3919 public CallbackType callbackType;
3920 public int error;
3921
3922 public CallbackValue(CallbackType type) {
3923 this.callbackType = type;
3924 this.error = PacketKeepalive.SUCCESS;
3925 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3926 }
3927
3928 public CallbackValue(CallbackType type, int error) {
3929 this.callbackType = type;
3930 this.error = error;
3931 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3932 }
3933
3934 @Override
3935 public boolean equals(Object o) {
3936 return o instanceof CallbackValue &&
3937 this.callbackType == ((CallbackValue) o).callbackType &&
3938 this.error == ((CallbackValue) o).error;
3939 }
3940
3941 @Override
3942 public String toString() {
3943 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3944 }
3945 }
3946
junyulai7c469172019-01-16 20:23:34 +08003947 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003948
3949 @Override
3950 public void onStarted() {
3951 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3952 }
3953
3954 @Override
3955 public void onStopped() {
3956 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3957 }
3958
3959 @Override
3960 public void onError(int error) {
3961 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3962 }
3963
Chalard Jeane7b24752019-06-20 16:01:19 +09003964 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3965 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003966 }
3967
Chalard Jeane7b24752019-06-20 16:01:19 +09003968 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003969 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3970 }
3971
Chalard Jeane7b24752019-06-20 16:01:19 +09003972 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003973 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3974 }
3975
Chalard Jeane7b24752019-06-20 16:01:19 +09003976 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003977 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3978 }
3979 }
3980
junyulai48eac1d42018-12-27 17:25:29 +08003981 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3982
3983 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3984
3985 private class CallbackValue {
3986 public CallbackType callbackType;
3987 public int error;
3988
3989 CallbackValue(CallbackType type) {
3990 this.callbackType = type;
3991 this.error = SocketKeepalive.SUCCESS;
3992 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3993 }
3994
3995 CallbackValue(CallbackType type, int error) {
3996 this.callbackType = type;
3997 this.error = error;
3998 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3999 }
4000
4001 @Override
4002 public boolean equals(Object o) {
4003 return o instanceof CallbackValue
4004 && this.callbackType == ((CallbackValue) o).callbackType
4005 && this.error == ((CallbackValue) o).error;
4006 }
4007
4008 @Override
4009 public String toString() {
4010 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
4011 error);
4012 }
4013 }
4014
4015 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08004016 private final Executor mExecutor;
4017
4018 TestSocketKeepaliveCallback(@NonNull Executor executor) {
4019 mExecutor = executor;
4020 }
junyulai48eac1d42018-12-27 17:25:29 +08004021
4022 @Override
4023 public void onStarted() {
4024 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
4025 }
4026
4027 @Override
4028 public void onStopped() {
4029 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
4030 }
4031
4032 @Override
4033 public void onError(int error) {
4034 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
4035 }
4036
Chalard Jeane7b24752019-06-20 16:01:19 +09004037 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
4038 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4039
junyulai48eac1d42018-12-27 17:25:29 +08004040 }
4041
Chalard Jeane7b24752019-06-20 16:01:19 +09004042 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08004043 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
4044 }
4045
Chalard Jeane7b24752019-06-20 16:01:19 +09004046 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08004047 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
4048 }
4049
Chalard Jeane7b24752019-06-20 16:01:19 +09004050 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08004051 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
4052 }
junyulai7c469172019-01-16 20:23:34 +08004053
4054 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004055 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08004056 CallbackValue cv = mCallbacks.peek();
4057 assertNull("Unexpected callback: " + cv, cv);
4058 }
junyulai48eac1d42018-12-27 17:25:29 +08004059 }
4060
Chalard Jeane7b24752019-06-20 16:01:19 +09004061 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004062 // Ensure the network is disconnected before we do anything.
4063 if (mWiFiNetworkAgent != null) {
4064 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
4065 }
4066
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004067 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09004068 ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004069 mWiFiNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09004070 b.expectBroadcast();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004071 verifyActiveNetwork(TRANSPORT_WIFI);
4072 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09004073 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004074 return mWiFiNetworkAgent.getNetwork();
4075 }
4076
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004077 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07004078 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004079 public void testPacketKeepalives() throws Exception {
4080 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4081 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4082 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4083 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4084 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4085
Nathan Harold63dd8132018-02-14 13:09:45 -08004086 final int validKaInterval = 15;
4087 final int invalidKaInterval = 9;
4088
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004089 LinkProperties lp = new LinkProperties();
4090 lp.setInterfaceName("wlan12");
4091 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4092 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4093 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4094 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4095
4096 Network notMyNet = new Network(61234);
4097 Network myNet = connectKeepaliveNetwork(lp);
4098
4099 TestKeepaliveCallback callback = new TestKeepaliveCallback();
4100 PacketKeepalive ka;
4101
4102 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08004103 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004104 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4105
Nathan Harold63dd8132018-02-14 13:09:45 -08004106 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004107 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4108
Nathan Harold63dd8132018-02-14 13:09:45 -08004109 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004110 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4111
Nathan Harold63dd8132018-02-14 13:09:45 -08004112 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004113 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4114
Nathan Harold63dd8132018-02-14 13:09:45 -08004115 // NAT-T is only supported for IPv4.
4116 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4117 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004118
Nathan Harold63dd8132018-02-14 13:09:45 -08004119 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004120 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4121
Nathan Harold63dd8132018-02-14 13:09:45 -08004122 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004123 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4124
Nathan Harold63dd8132018-02-14 13:09:45 -08004125 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004126 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4127
Nathan Harold63dd8132018-02-14 13:09:45 -08004128 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004129 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4130
4131 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004132 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08004133 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004134 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004135 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004136 ka.stop();
4137 callback.expectStopped();
4138
4139 // Check that deleting the IP address stops the keepalive.
4140 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08004141 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004142 callback.expectStarted();
4143 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4144 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4145 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4146 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4147 mWiFiNetworkAgent.sendLinkProperties(lp);
4148
4149 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004150 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004151 callback.expectStarted();
4152 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004153 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004154 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4155
4156 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004157 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004158 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004159 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004160 ka.stop();
4161
4162 // Reconnect.
4163 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004164 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004165
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004166 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4167 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004168 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004169 callback.expectStarted();
4170
4171 // The second one gets slot 2.
4172 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4173 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004174 PacketKeepalive ka2 = mCm.startNattKeepalive(
4175 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004176 callback2.expectStarted();
4177
4178 // Now stop the first one and create a third. This also gets slot 1.
4179 ka.stop();
4180 callback.expectStopped();
4181
4182 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4183 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004184 PacketKeepalive ka3 = mCm.startNattKeepalive(
4185 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004186 callback3.expectStarted();
4187
4188 ka2.stop();
4189 callback2.expectStopped();
4190
4191 ka3.stop();
4192 callback3.expectStopped();
4193 }
Udam Sainib7c24872016-01-04 12:16:14 -08004194
Xiao Maa4637112019-02-07 15:03:57 +09004195 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09004196 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
4197 throws Exception {
junyulai06835112019-01-03 18:50:15 +08004198 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004199 final Executor executorInline = (Runnable r) -> r.run();
4200 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08004201 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004202 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004203 }
junyulai06835112019-01-03 18:50:15 +08004204
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004205 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004206 public void testNattSocketKeepalives() throws Exception {
4207 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4208 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08004209 }
4210
4211 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004212 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08004213 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004214 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004215 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4216 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4217 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4218 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4219 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4220
4221 final int validKaInterval = 15;
4222 final int invalidKaInterval = 9;
4223
4224 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004225 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4226 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004227
junyulai48eac1d42018-12-27 17:25:29 +08004228 LinkProperties lp = new LinkProperties();
4229 lp.setInterfaceName("wlan12");
4230 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4231 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4232 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4233 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4234
4235 Network notMyNet = new Network(61234);
4236 Network myNet = connectKeepaliveNetwork(lp);
4237
junyulai7c469172019-01-16 20:23:34 +08004238 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004239
4240 // Attempt to start keepalives with invalid parameters and check for errors.
4241 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004242 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4243 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4244 ka.start(validKaInterval);
4245 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4246 }
junyulai48eac1d42018-12-27 17:25:29 +08004247
4248 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004249 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4250 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4251 ka.start(invalidKaInterval);
4252 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4253 }
junyulai48eac1d42018-12-27 17:25:29 +08004254
4255 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004256 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4257 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4258 ka.start(validKaInterval);
4259 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4260 }
junyulai48eac1d42018-12-27 17:25:29 +08004261
4262 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004263 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4264 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4265 ka.start(validKaInterval);
4266 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4267 }
junyulai48eac1d42018-12-27 17:25:29 +08004268
4269 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004270 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4271 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4272 ka.start(validKaInterval);
4273 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4274 }
junyulai48eac1d42018-12-27 17:25:29 +08004275
4276 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004277 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4278 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4279 ka.start(validKaInterval);
4280 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4281 }
junyulai48eac1d42018-12-27 17:25:29 +08004282
4283 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004284 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004285 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4286 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4287 ka.start(validKaInterval);
4288 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004289 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004290 ka.stop();
4291 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004292
junyulai0c666972019-03-04 22:45:36 +08004293 // Check that keepalive could be restarted.
4294 ka.start(validKaInterval);
4295 callback.expectStarted();
4296 ka.stop();
4297 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004298
junyulai0c666972019-03-04 22:45:36 +08004299 // Check that keepalive can be restarted without waiting for callback.
4300 ka.start(validKaInterval);
4301 callback.expectStarted();
4302 ka.stop();
4303 ka.start(validKaInterval);
4304 callback.expectStopped();
4305 callback.expectStarted();
4306 ka.stop();
4307 callback.expectStopped();
4308 }
junyulai7c469172019-01-16 20:23:34 +08004309
junyulai48eac1d42018-12-27 17:25:29 +08004310 // Check that deleting the IP address stops the keepalive.
4311 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004312 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4313 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4314 ka.start(validKaInterval);
4315 callback.expectStarted();
4316 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4317 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4318 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4319 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4320 mWiFiNetworkAgent.sendLinkProperties(lp);
4321 }
junyulai48eac1d42018-12-27 17:25:29 +08004322
4323 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004324 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4325 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4326 ka.start(validKaInterval);
4327 callback.expectStarted();
4328 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004329 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004330 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004331
junyulai0c666972019-03-04 22:45:36 +08004332 // ... and that stopping it after that has no adverse effects.
4333 waitForIdle();
4334 final Network myNetAlias = myNet;
4335 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4336 ka.stop();
4337 callback.assertNoCallback();
4338 }
junyulai48eac1d42018-12-27 17:25:29 +08004339
4340 // Reconnect.
4341 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004342 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08004343
4344 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4345 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004346 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004347 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4348 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4349 ka.start(validKaInterval);
4350 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004351
junyulai0c666972019-03-04 22:45:36 +08004352 // The second one gets slot 2.
4353 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004354 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4355 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004356 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4357 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4358 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4359 ka2.start(validKaInterval);
4360 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004361
junyulai0c666972019-03-04 22:45:36 +08004362 ka.stop();
4363 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004364
junyulai0c666972019-03-04 22:45:36 +08004365 ka2.stop();
4366 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004367
junyulai0c666972019-03-04 22:45:36 +08004368 testSocket.close();
4369 testSocket2.close();
4370 }
4371 }
junyulai06835112019-01-03 18:50:15 +08004372
junyulai15178152019-03-27 11:00:37 +08004373 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004374 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4375 // assertFalse(isUdpPortInUse(srcPort));
4376 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004377
junyulai06835112019-01-03 18:50:15 +08004378 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004379 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004380 mWiFiNetworkAgent = null;
4381 }
4382
4383 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004384 public void testTcpSocketKeepalives() throws Exception {
4385 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004386 }
4387
4388 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4389 final int srcPortV4 = 12345;
4390 final int srcPortV6 = 23456;
4391 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4392 final InetAddress myIPv6 = InetAddress.getByName("::1");
4393
4394 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004395
4396 final LinkProperties lp = new LinkProperties();
4397 lp.setInterfaceName("wlan12");
4398 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4399 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4400 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4401 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4402
4403 final Network notMyNet = new Network(61234);
4404 final Network myNet = connectKeepaliveNetwork(lp);
4405
4406 final Socket testSocketV4 = new Socket();
4407 final Socket testSocketV6 = new Socket();
4408
junyulai7c469172019-01-16 20:23:34 +08004409 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004410
4411 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4412 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004413 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4414 notMyNet, testSocketV4, executor, callback)) {
4415 ka.start(validKaInterval);
4416 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4417 }
Xiao Maa4637112019-02-07 15:03:57 +09004418
4419 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004420 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4421 myNet, testSocketV4, executor, callback)) {
4422 ka.start(validKaInterval);
4423 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4424 }
Xiao Maa4637112019-02-07 15:03:57 +09004425
4426 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004427 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4428 myNet, testSocketV6, executor, callback)) {
4429 ka.start(validKaInterval);
4430 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4431 }
Xiao Maa4637112019-02-07 15:03:57 +09004432
4433 // Bind the socket address
4434 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4435 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4436
4437 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004438 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4439 myNet, testSocketV4, executor, callback)) {
4440 ka.start(validKaInterval);
4441 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4442 }
Xiao Maa4637112019-02-07 15:03:57 +09004443
4444 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004445 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4446 myNet, testSocketV6, executor, callback)) {
4447 ka.start(validKaInterval);
4448 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4449 }
Xiao Maa4637112019-02-07 15:03:57 +09004450
4451 testSocketV4.close();
4452 testSocketV6.close();
4453
4454 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004455 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004456 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004457 }
4458
junyulai0c666972019-03-04 22:45:36 +08004459 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004460 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4461 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4462 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4463 final int validKaInterval = 15;
4464
4465 // Prepare the target network.
4466 LinkProperties lp = new LinkProperties();
4467 lp.setInterfaceName("wlan12");
4468 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4469 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4470 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004471 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4472 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004473
4474 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4475
4476 // Prepare the target file descriptor, keep only one instance.
4477 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004478 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4479 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004480 final ParcelFileDescriptor testPfd =
4481 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4482 testSocket.close();
4483 assertTrue(isUdpPortInUse(srcPort));
4484
4485 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4486 // block.
4487 try (SocketKeepalive ka = mCm.createNattKeepalive(
4488 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4489 ka.start(validKaInterval);
4490 callback.expectStarted();
4491 ka.stop();
4492 callback.expectStopped();
4493 }
4494
4495 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4496 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4497 // address.
4498 assertTrue(isUdpPortInUse(srcPort));
4499 final InetSocketAddress sa =
4500 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4501 assertEquals(anyIPv4, sa.getAddress());
4502
4503 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004504 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4505 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004506
4507 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004508 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004509 mWiFiNetworkAgent = null;
4510 }
4511
4512 private static boolean isUdpPortInUse(int port) {
4513 try (DatagramSocket ignored = new DatagramSocket(port)) {
4514 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004515 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004516 return true;
4517 }
4518 }
4519
junyulai48eac1d42018-12-27 17:25:29 +08004520 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004521 public void testGetCaptivePortalServerUrl() throws Exception {
4522 String url = mCm.getCaptivePortalServerUrl();
4523 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4524 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004525
4526 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004527 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004528 synchronized(sLock) {
4529 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004530 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004531 }
4532 return sNetwork != null;
4533 }
4534 }
4535
Chalard Jeane7b24752019-06-20 16:01:19 +09004536 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004537 synchronized(sLock) {
4538 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004539 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004540 }
4541 return sNetwork == null;
4542 }
4543 }
4544 }
4545
4546 private void assertPinnedToWifiWithCellDefault() {
4547 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4548 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4549 }
4550
4551 private void assertPinnedToWifiWithWifiDefault() {
4552 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4553 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4554 }
4555
4556 private void assertNotPinnedToWifi() {
4557 assertNull(mCm.getBoundNetworkForProcess());
4558 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4559 }
4560
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004561 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004562 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004563 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4564 .addTransportType(TRANSPORT_WIFI)
4565 .build();
4566 assertNull(mCm.getBoundNetworkForProcess());
4567
4568 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4569 assertNull(mCm.getBoundNetworkForProcess());
4570
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004571 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004572 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004573 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004574 mWiFiNetworkAgent.connect(false);
4575
4576 // When wi-fi connects, expect to be pinned.
4577 assertTrue(TestNetworkPinner.awaitPin(100));
4578 assertPinnedToWifiWithCellDefault();
4579
4580 // Disconnect and expect the pin to drop.
4581 mWiFiNetworkAgent.disconnect();
4582 assertTrue(TestNetworkPinner.awaitUnpin(100));
4583 assertNotPinnedToWifi();
4584
4585 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004586 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004587 mWiFiNetworkAgent.connect(false);
4588 assertFalse(TestNetworkPinner.awaitPin(100));
4589 assertNotPinnedToWifi();
4590
4591 // Pinning while connected causes the pin to take effect immediately.
4592 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4593 assertTrue(TestNetworkPinner.awaitPin(100));
4594 assertPinnedToWifiWithCellDefault();
4595
4596 // Explicitly unpin and expect to use the default network again.
4597 TestNetworkPinner.unpin();
4598 assertNotPinnedToWifi();
4599
4600 // Disconnect cell and wifi.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09004601 ExpectedBroadcast b = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004602 mCellNetworkAgent.disconnect();
4603 mWiFiNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09004604 b.expectBroadcast();
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004605
4606 // Pinning takes effect even if the pinned network is the default when the pin is set...
4607 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004608 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004609 mWiFiNetworkAgent.connect(false);
4610 assertTrue(TestNetworkPinner.awaitPin(100));
4611 assertPinnedToWifiWithWifiDefault();
4612
4613 // ... and is maintained even when that network is no longer the default.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09004614 b = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004615 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004616 mCellNetworkAgent.connect(true);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09004617 b.expectBroadcast();
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004618 assertPinnedToWifiWithCellDefault();
4619 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004620
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004621 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004622 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004623 // We can only have 99 callbacks, because MultipathPolicyTracker is
4624 // already one of them.
4625 final int MAX_REQUESTS = 99;
4626 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004627 final int INTENTS = 10;
4628 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4629
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004630 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004631 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004632
Hugo Benichi893a7622017-09-29 09:34:08 +09004633 int j = 0;
4634 while (j++ < CALLBACKS / 2) {
4635 NetworkCallback cb = new NetworkCallback();
4636 mCm.requestNetwork(networkRequest, cb);
4637 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004638 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004639 while (j++ < CALLBACKS) {
4640 NetworkCallback cb = new NetworkCallback();
4641 mCm.registerNetworkCallback(networkRequest, cb);
4642 registered.add(cb);
4643 }
4644 j = 0;
4645 while (j++ < INTENTS / 2) {
4646 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4647 mCm.requestNetwork(networkRequest, pi);
4648 registered.add(pi);
4649 }
4650 while (j++ < INTENTS) {
4651 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4652 mCm.registerNetworkCallback(networkRequest, pi);
4653 registered.add(pi);
4654 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004655
Hugo Benichi893a7622017-09-29 09:34:08 +09004656 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004657 assertThrows(TooManyRequestsException.class, () ->
4658 mCm.requestNetwork(networkRequest, new NetworkCallback())
4659 );
4660 assertThrows(TooManyRequestsException.class, () ->
4661 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4662 );
4663 assertThrows(TooManyRequestsException.class, () ->
4664 mCm.requestNetwork(networkRequest,
4665 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4666 );
4667 assertThrows(TooManyRequestsException.class, () ->
4668 mCm.registerNetworkCallback(networkRequest,
4669 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4670 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004671
Hugo Benichi893a7622017-09-29 09:34:08 +09004672 for (Object o : registered) {
4673 if (o instanceof NetworkCallback) {
4674 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004675 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004676 if (o instanceof PendingIntent) {
4677 mCm.unregisterNetworkCallback((PendingIntent)o);
4678 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004679 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004680 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004681
4682 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4683 for (int i = 0; i < MAX_REQUESTS; i++) {
4684 NetworkCallback networkCallback = new NetworkCallback();
4685 mCm.requestNetwork(networkRequest, networkCallback);
4686 mCm.unregisterNetworkCallback(networkCallback);
4687 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004688 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004689
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004690 for (int i = 0; i < MAX_REQUESTS; i++) {
4691 NetworkCallback networkCallback = new NetworkCallback();
4692 mCm.registerNetworkCallback(networkRequest, networkCallback);
4693 mCm.unregisterNetworkCallback(networkCallback);
4694 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004695 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004696
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004697 for (int i = 0; i < MAX_REQUESTS; i++) {
4698 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004699 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004700 mCm.requestNetwork(networkRequest, pendingIntent);
4701 mCm.unregisterNetworkCallback(pendingIntent);
4702 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004703 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004704
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004705 for (int i = 0; i < MAX_REQUESTS; i++) {
4706 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004707 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004708 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4709 mCm.unregisterNetworkCallback(pendingIntent);
4710 }
4711 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004712
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004713 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004714 public void testNetworkInfoOfTypeNone() throws Exception {
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09004715 ExpectedBroadcast b = registerConnectivityBroadcast(1);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004716
4717 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004718 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004719 assertNull(mCm.getActiveNetworkInfo());
4720
4721 Network[] allNetworks = mCm.getAllNetworks();
4722 assertLength(1, allNetworks);
4723 Network network = allNetworks[0];
4724 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4725 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4726
4727 final NetworkRequest request =
4728 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4729 final TestNetworkCallback callback = new TestNetworkCallback();
4730 mCm.registerNetworkCallback(request, callback);
4731
Hugo Benichic1014502017-07-19 10:10:52 +09004732 // Bring up wifi aware network.
lucaslin783f2212019-10-22 18:27:33 +08004733 wifiAware.connect(false, false, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004734 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004735
4736 assertNull(mCm.getActiveNetworkInfo());
4737 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004738 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004739 // of this test. Fix it and uncomment the assert below.
4740 //assertEmpty(mCm.getAllNetworkInfo());
4741
Hugo Benichic1014502017-07-19 10:10:52 +09004742 // Disconnect wifi aware network.
4743 wifiAware.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09004744 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004745 mCm.unregisterNetworkCallback(callback);
4746
4747 verifyNoNetwork();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09004748 b.expectNoBroadcast(10);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004749 }
4750
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004751 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004752 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4753 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4754 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4755 assertNull(mCm.getNetworkForType(TYPE_NONE));
4756 assertNull(mCm.getLinkProperties(TYPE_NONE));
4757 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4758
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004759 assertThrows(IllegalArgumentException.class,
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004760 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004761
4762 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004763 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4764 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004765 // TODO: let test context have configuration application target sdk version
4766 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004767 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4768 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4769 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004770 }
4771
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004772 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004773 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004774 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4775 .addTransportType(TRANSPORT_WIFI).build();
4776 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4777 mCm.registerNetworkCallback(networkRequest, networkCallback);
4778
4779 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004780 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004781 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4782 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4783 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4784 lp.addLinkAddress(myIpv4Address);
4785 lp.addRoute(myIpv4DefaultRoute);
4786
4787 // Verify direct routes are added when network agent is first registered in
4788 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004789 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004790 networkAgent.connect(true);
Chalard Jean059c4262019-09-30 17:51:12 +09004791 networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
4792 networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
4793 CallbackEntry.LinkPropertiesChanged cbi =
4794 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004795 networkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004796 networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004797 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4798 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004799 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004800 Arrays.asList(myIpv4DefaultRoute));
4801 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4802 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4803
4804 // Verify direct routes are added during subsequent link properties updates.
4805 LinkProperties newLp = new LinkProperties(lp);
4806 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4807 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4808 newLp.addLinkAddress(myIpv6Address1);
4809 newLp.addLinkAddress(myIpv6Address2);
4810 networkAgent.sendLinkProperties(newLp);
Chalard Jean059c4262019-09-30 17:51:12 +09004811 cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004812 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004813 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004814 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4815 Arrays.asList(myIpv4DefaultRoute));
4816 mCm.unregisterNetworkCallback(networkCallback);
4817 }
4818
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004819 private <T> void assertSameElementsNoDuplicates(T[] expected, T[] actual) {
4820 // Easier to implement than a proper "assertSameElements" method that also correctly deals
4821 // with duplicates.
4822 final String msg = Arrays.toString(expected) + " != " + Arrays.toString(actual);
4823 assertEquals(msg, expected.length, actual.length);
4824 Set expectedSet = new ArraySet<>(Arrays.asList(expected));
4825 assertEquals("expected contains duplicates", expectedSet.size(), expected.length);
4826 // actual cannot have duplicates because it's the same length and has the same elements.
4827 Set actualSet = new ArraySet<>(Arrays.asList(actual));
4828 assertEquals(expectedSet, actualSet);
4829 }
4830
4831 private void expectForceUpdateIfaces(Network[] networks, String defaultIface,
4832 Integer vpnUid, String vpnIfname, String[] underlyingIfaces) throws Exception {
4833 ArgumentCaptor<Network[]> networksCaptor = ArgumentCaptor.forClass(Network[].class);
4834 ArgumentCaptor<VpnInfo[]> vpnInfosCaptor = ArgumentCaptor.forClass(VpnInfo[].class);
4835
4836 verify(mStatsService, atLeastOnce()).forceUpdateIfaces(networksCaptor.capture(),
4837 any(NetworkState[].class), eq(defaultIface), vpnInfosCaptor.capture());
4838
4839 assertSameElementsNoDuplicates(networksCaptor.getValue(), networks);
4840
4841 VpnInfo[] infos = vpnInfosCaptor.getValue();
4842 if (vpnUid != null) {
4843 assertEquals("Should have exactly one VPN:", 1, infos.length);
4844 VpnInfo info = infos[0];
4845 assertEquals("Unexpected VPN owner:", (int) vpnUid, info.ownerUid);
4846 assertEquals("Unexpected VPN interface:", vpnIfname, info.vpnIface);
4847 assertSameElementsNoDuplicates(underlyingIfaces, info.underlyingIfaces);
4848 } else {
4849 assertEquals(0, infos.length);
4850 return;
4851 }
4852 }
4853
4854 private void expectForceUpdateIfaces(Network[] networks, String defaultIface) throws Exception {
4855 expectForceUpdateIfaces(networks, defaultIface, null, null, new String[0]);
4856 }
4857
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004858 @Test
4859 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004860 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4861 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004862
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004863 final Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4864 final Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
Varun Anandd33cbc62019-02-07 14:13:13 -08004865
4866 LinkProperties cellLp = new LinkProperties();
4867 cellLp.setInterfaceName(MOBILE_IFNAME);
4868 LinkProperties wifiLp = new LinkProperties();
4869 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004870
4871 // Simple connection should have updated ifaces
4872 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004873 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004874 waitForIdle();
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004875 expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004876 reset(mStatsService);
4877
4878 // Default network switch should update ifaces.
4879 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004880 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004881 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004882 assertEquals(wifiLp, mService.getActiveLinkProperties());
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004883 expectForceUpdateIfaces(onlyWifi, WIFI_IFNAME);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004884 reset(mStatsService);
4885
4886 // Disconnect should update ifaces.
4887 mWiFiNetworkAgent.disconnect();
4888 waitForIdle();
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004889 expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004890 reset(mStatsService);
4891
4892 // Metered change should update ifaces
4893 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4894 waitForIdle();
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004895 expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004896 reset(mStatsService);
4897
4898 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4899 waitForIdle();
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004900 expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004901 reset(mStatsService);
4902
4903 // Captive portal change shouldn't update ifaces
4904 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4905 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004906 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004907 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4908 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004909 reset(mStatsService);
4910
4911 // Roaming change should update ifaces
4912 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4913 waitForIdle();
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004914 expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
4915 reset(mStatsService);
4916
4917 // Test VPNs.
4918 final LinkProperties lp = new LinkProperties();
4919 lp.setInterfaceName(VPN_IFNAME);
4920
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09004921 mMockVpn.establishForMyUid(lp);
4922
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004923 final Network[] cellAndVpn = new Network[] {
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09004924 mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()};
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004925
4926 // A VPN with default (null) underlying networks sets the underlying network's interfaces...
4927 expectForceUpdateIfaces(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
4928 new String[]{MOBILE_IFNAME});
4929
4930 // ...and updates them as the default network switches.
4931 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4932 mWiFiNetworkAgent.connect(false);
4933 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittia3bdd1b2020-11-25 22:59:08 +09004934 final Network[] onlyNull = new Network[]{null};
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004935 final Network[] wifiAndVpn = new Network[] {
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09004936 mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork()};
Lorenzo Colittia3bdd1b2020-11-25 22:59:08 +09004937 final Network[] cellAndWifi = new Network[] {
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004938 mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()};
Lorenzo Colittia3bdd1b2020-11-25 22:59:08 +09004939 final Network[] cellNullAndWifi = new Network[] {
4940 mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()};
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004941
4942 waitForIdle();
4943 assertEquals(wifiLp, mService.getActiveLinkProperties());
4944 expectForceUpdateIfaces(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
4945 new String[]{WIFI_IFNAME});
4946 reset(mStatsService);
4947
4948 // A VPN that sets its underlying networks passes the underlying interfaces, and influences
4949 // the default interface sent to NetworkStatsService by virtue of applying to the system
4950 // server UID (or, in this test, to the test's UID). This is the reason for sending
4951 // MOBILE_IFNAME even though the default network is wifi.
4952 // TODO: fix this to pass in the actual default network interface. Whether or not the VPN
4953 // applies to the system server UID should not have any bearing on network stats.
4954 mService.setUnderlyingNetworksForVpn(onlyCell);
4955 waitForIdle();
4956 expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
4957 new String[]{MOBILE_IFNAME});
4958 reset(mStatsService);
4959
4960 mService.setUnderlyingNetworksForVpn(cellAndWifi);
4961 waitForIdle();
4962 expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
4963 new String[]{MOBILE_IFNAME, WIFI_IFNAME});
4964 reset(mStatsService);
4965
Lorenzo Colittia3bdd1b2020-11-25 22:59:08 +09004966 // Null underlying networks are ignored.
4967 mService.setUnderlyingNetworksForVpn(cellNullAndWifi);
4968 waitForIdle();
4969 expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
4970 new String[]{MOBILE_IFNAME, WIFI_IFNAME});
4971 reset(mStatsService);
4972
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09004973 // If an underlying network disconnects, that interface should no longer be underlying.
4974 // This doesn't actually work because disconnectAndDestroyNetwork only notifies
4975 // NetworkStatsService before the underlying network is actually removed. So the underlying
4976 // network will only be removed if notifyIfacesChangedForNetworkStats is called again. This
4977 // could result in incorrect data usage measurements if the interface used by the
4978 // disconnected network is reused by a system component that does not register an agent for
4979 // it (e.g., tethering).
4980 mCellNetworkAgent.disconnect();
4981 waitForIdle();
4982 assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork()));
4983 expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
4984 new String[]{MOBILE_IFNAME, WIFI_IFNAME});
4985
4986 // Confirm that we never tell NetworkStatsService that cell is no longer the underlying
4987 // network for the VPN...
4988 verify(mStatsService, never()).forceUpdateIfaces(any(Network[].class),
4989 any(NetworkState[].class), any() /* anyString() doesn't match null */,
4990 argThat(infos -> infos[0].underlyingIfaces.length == 1
4991 && WIFI_IFNAME.equals(infos[0].underlyingIfaces[0])));
4992 verifyNoMoreInteractions(mStatsService);
4993 reset(mStatsService);
4994
4995 // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be
4996 // called again, it does. For example, connect Ethernet, but with a low score, such that it
4997 // does not become the default network.
4998 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
4999 mEthernetNetworkAgent.adjustScore(-40);
5000 mEthernetNetworkAgent.connect(false);
5001 waitForIdle();
5002 verify(mStatsService).forceUpdateIfaces(any(Network[].class),
5003 any(NetworkState[].class), any() /* anyString() doesn't match null */,
5004 argThat(vpnInfos -> vpnInfos[0].underlyingIfaces.length == 1
5005 && WIFI_IFNAME.equals(vpnInfos[0].underlyingIfaces[0])));
5006 mEthernetNetworkAgent.disconnect();
Lorenzo Colittia3bdd1b2020-11-25 22:59:08 +09005007 waitForIdle();
Lorenzo Colitti66f3d4b2020-11-17 23:23:58 +09005008 reset(mStatsService);
5009
5010 // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo
5011 // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes
5012 // NetworkStatsFactory#adjustForTunAnd464Xlat not to attempt any VPN data migration, which
5013 // is probably a performance improvement (though it's very unlikely that a VPN would declare
5014 // no underlying networks).
5015 // Also, for the same reason as above, the active interface passed in is null.
5016 mService.setUnderlyingNetworksForVpn(new Network[0]);
5017 waitForIdle();
5018 expectForceUpdateIfaces(wifiAndVpn, null);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06005019 reset(mStatsService);
Lorenzo Colittia3bdd1b2020-11-25 22:59:08 +09005020
5021 // Specifying only a null underlying network is the same as no networks.
5022 mService.setUnderlyingNetworksForVpn(onlyNull);
5023 waitForIdle();
5024 expectForceUpdateIfaces(wifiAndVpn, null);
5025 reset(mStatsService);
5026
5027 // Specifying networks that are all disconnected is the same as specifying no networks.
5028 mService.setUnderlyingNetworksForVpn(onlyCell);
5029 waitForIdle();
5030 expectForceUpdateIfaces(wifiAndVpn, null);
5031 reset(mStatsService);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06005032 }
5033
Erik Klinee89953b2018-01-11 16:11:10 +09005034 @Test
5035 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07005036 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07005037
5038 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08005039 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005040
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005041 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09005042 waitForIdle();
waynema13516842019-03-12 18:13:49 +08005043 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005044 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005045
5046 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07005047 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09005048 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5049 // "is-reachable" testing in order to not program netd with unreachable
5050 // nameservers that it might try repeated to validate.
5051 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07005052 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5053 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09005054 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07005055 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5056 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09005057 mCellNetworkAgent.sendLinkProperties(cellLp);
5058 mCellNetworkAgent.connect(false);
5059 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005060
5061 verify(mMockDnsResolver, times(1)).createNetworkCache(
5062 eq(mCellNetworkAgent.getNetwork().netId));
5063 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08005064 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005065 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005066
5067 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5068 mCellNetworkAgent.sendLinkProperties(cellLp);
5069 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005070 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005071 mResolverParamsParcelCaptor.capture());
5072 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5073 assertEquals(1, resolvrParams.servers.length);
5074 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07005075 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08005076 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08005077 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005078
5079 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5080 mCellNetworkAgent.sendLinkProperties(cellLp);
5081 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005082 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005083 mResolverParamsParcelCaptor.capture());
5084 resolvrParams = mResolverParamsParcelCaptor.getValue();
5085 assertEquals(2, resolvrParams.servers.length);
5086 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09005087 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07005088 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08005089 assertEquals(2, resolvrParams.tlsServers.length);
5090 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07005091 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005092 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09005093
5094 final String TLS_SPECIFIER = "tls.example.com";
5095 final String TLS_SERVER6 = "2001:db8:53::53";
5096 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
5097 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005098 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
5099 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
5100
Erik Kline117e7f32018-03-04 21:01:01 +09005101 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08005102 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005103 mResolverParamsParcelCaptor.capture());
5104 resolvrParams = mResolverParamsParcelCaptor.getValue();
5105 assertEquals(2, resolvrParams.servers.length);
5106 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09005107 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08005108 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09005109 }
5110
Erik Kline79c6d052018-03-21 07:18:33 -07005111 @Test
chenbruce5d955622020-02-20 14:28:31 +08005112 public void testDnsConfigurationTransTypesPushed() throws Exception {
5113 // Clear any interactions that occur as a result of CS starting up.
5114 reset(mMockDnsResolver);
5115
5116 final NetworkRequest request = new NetworkRequest.Builder()
5117 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
5118 .build();
5119 final TestNetworkCallback callback = new TestNetworkCallback();
5120 mCm.registerNetworkCallback(request, callback);
5121
5122 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5123 mWiFiNetworkAgent.connect(false);
5124 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5125 verify(mMockDnsResolver, times(1)).createNetworkCache(
5126 eq(mWiFiNetworkAgent.getNetwork().netId));
5127 verify(mMockDnsResolver, times(2)).setResolverConfiguration(
5128 mResolverParamsParcelCaptor.capture());
5129 final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
5130 assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
5131 reset(mMockDnsResolver);
5132 }
5133
5134 @Test
lucaslin783f2212019-10-22 18:27:33 +08005135 public void testPrivateDnsNotification() throws Exception {
5136 NetworkRequest request = new NetworkRequest.Builder()
5137 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
5138 .build();
5139 TestNetworkCallback callback = new TestNetworkCallback();
5140 mCm.registerNetworkCallback(request, callback);
5141 // Bring up wifi.
5142 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5143 mWiFiNetworkAgent.connect(false);
5144 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
5145 // Private DNS resolution failed, checking if the notification will be shown or not.
5146 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
5147 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5148 waitForIdle();
5149 // If network validation failed, NetworkMonitor will re-evaluate the network.
5150 // ConnectivityService should filter the redundant notification. This part is trying to
5151 // simulate that situation and check if ConnectivityService could filter that case.
5152 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5153 waitForIdle();
5154 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
5155 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
5156 // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
5157 // shown.
5158 mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
5159 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5160 waitForIdle();
5161 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
5162 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
5163 // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
5164 // shown again.
5165 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
5166 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5167 waitForIdle();
5168 verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
5169 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
5170 }
5171
5172 @Test
Erik Kline79c6d052018-03-21 07:18:33 -07005173 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07005174 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08005175 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005176
5177 // The default on Android is opportunistic mode ("Automatic").
5178 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5179
dalyk1fcb7392018-03-05 12:42:22 -05005180 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5181 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5182 .addTransportType(TRANSPORT_CELLULAR).build();
5183 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5184
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005185 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07005186 waitForIdle();
5187 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08005188 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08005189 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07005190
5191 final LinkProperties cellLp = new LinkProperties();
5192 cellLp.setInterfaceName(MOBILE_IFNAME);
5193 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
5194 // "is-reachable" testing in order to not program netd with unreachable
5195 // nameservers that it might try repeated to validate.
5196 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
5197 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
5198 MOBILE_IFNAME));
5199 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
5200 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5201 MOBILE_IFNAME));
5202 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5203 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5204
5205 mCellNetworkAgent.sendLinkProperties(cellLp);
5206 mCellNetworkAgent.connect(false);
5207 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005208 verify(mMockDnsResolver, times(1)).createNetworkCache(
5209 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08005210 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005211 mResolverParamsParcelCaptor.capture());
5212 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5213 assertEquals(2, resolvrParams.tlsServers.length);
5214 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005215 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07005216 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08005217 assertEquals(2, resolvrParams.tlsServers.length);
5218 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005219 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08005220 reset(mMockDnsResolver);
Chalard Jean059c4262019-09-30 17:51:12 +09005221 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
5222 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05005223 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005224 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
5225 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
5226 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005227 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005228 assertFalse(cbi.getLp().isPrivateDnsActive());
5229 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07005230
5231 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005232 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005233 mResolverParamsParcelCaptor.capture());
5234 resolvrParams = mResolverParamsParcelCaptor.getValue();
5235 assertEquals(2, resolvrParams.servers.length);
5236 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005237 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08005238 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005239 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005240
5241 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005242 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005243 mResolverParamsParcelCaptor.capture());
5244 resolvrParams = mResolverParamsParcelCaptor.getValue();
5245 assertEquals(2, resolvrParams.servers.length);
5246 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005247 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08005248 assertEquals(2, resolvrParams.tlsServers.length);
5249 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005250 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08005251 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005252 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005253
dalyk1fcb7392018-03-05 12:42:22 -05005254 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5255 // Can't test dns configuration for strict mode without properly mocking
5256 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean059c4262019-09-30 17:51:12 +09005257 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005258 mCellNetworkAgent);
5259 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005260 assertTrue(cbi.getLp().isPrivateDnsActive());
5261 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005262 }
5263
5264 @Test
5265 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5266 // The default on Android is opportunistic mode ("Automatic").
5267 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5268
5269 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5270 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5271 .addTransportType(TRANSPORT_CELLULAR).build();
5272 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5273
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005274 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05005275 waitForIdle();
5276 LinkProperties lp = new LinkProperties();
5277 mCellNetworkAgent.sendLinkProperties(lp);
5278 mCellNetworkAgent.connect(false);
5279 waitForIdle();
Chalard Jean059c4262019-09-30 17:51:12 +09005280 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
5281 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05005282 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005283 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
5284 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
5285 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005286 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005287 assertFalse(cbi.getLp().isPrivateDnsActive());
5288 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005289 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005290 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005291
5292 // Send a validation event for a server that is not part of the current
5293 // resolver config. The validation event should be ignored.
5294 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5295 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5296 cellNetworkCallback.assertNoCallback();
5297
5298 // Add a dns server to the LinkProperties.
5299 LinkProperties lp2 = new LinkProperties(lp);
5300 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5301 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean059c4262019-09-30 17:51:12 +09005302 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005303 mCellNetworkAgent);
5304 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005305 assertFalse(cbi.getLp().isPrivateDnsActive());
5306 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005307 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005308 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005309
5310 // Send a validation event containing a hostname that is not part of
5311 // the current resolver config. The validation event should be ignored.
5312 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5313 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5314 cellNetworkCallback.assertNoCallback();
5315
5316 // Send a validation event where validation failed.
5317 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5318 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5319 cellNetworkCallback.assertNoCallback();
5320
5321 // Send a validation event where validation succeeded for a server in
5322 // the current resolver config. A LinkProperties callback with updated
5323 // private dns fields should be sent.
5324 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5325 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean059c4262019-09-30 17:51:12 +09005326 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005327 mCellNetworkAgent);
5328 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005329 assertTrue(cbi.getLp().isPrivateDnsActive());
5330 assertNull(cbi.getLp().getPrivateDnsServerName());
5331 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005332
5333 // The private dns fields in LinkProperties should be preserved when
5334 // the network agent sends unrelated changes.
5335 LinkProperties lp3 = new LinkProperties(lp2);
5336 lp3.setMtu(1300);
5337 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean059c4262019-09-30 17:51:12 +09005338 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005339 mCellNetworkAgent);
5340 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005341 assertTrue(cbi.getLp().isPrivateDnsActive());
5342 assertNull(cbi.getLp().getPrivateDnsServerName());
5343 checkDnsServers(cbi.getLp(), dnsServers);
5344 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05005345
5346 // Removing the only validated server should affect the private dns
5347 // fields in LinkProperties.
5348 LinkProperties lp4 = new LinkProperties(lp3);
5349 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5350 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean059c4262019-09-30 17:51:12 +09005351 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005352 mCellNetworkAgent);
5353 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005354 assertFalse(cbi.getLp().isPrivateDnsActive());
5355 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005356 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005357 checkDnsServers(cbi.getLp(), dnsServers);
5358 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005359 }
5360
Rubin Xu1bb5c082017-09-05 18:40:49 +01005361 private void checkDirectlyConnectedRoutes(Object callbackObj,
5362 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5363 assertTrue(callbackObj instanceof LinkProperties);
5364 LinkProperties lp = (LinkProperties) callbackObj;
5365
5366 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5367 expectedRoutes.addAll(otherRoutes);
5368 for (LinkAddress address : linkAddresses) {
5369 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5370 // Duplicates in linkAddresses are considered failures
5371 assertTrue(expectedRoutes.add(localRoute));
5372 }
5373 List<RouteInfo> observedRoutes = lp.getRoutes();
5374 assertEquals(expectedRoutes.size(), observedRoutes.size());
5375 assertTrue(observedRoutes.containsAll(expectedRoutes));
5376 }
5377
dalyk1fcb7392018-03-05 12:42:22 -05005378 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5379 assertTrue(callbackObj instanceof LinkProperties);
5380 LinkProperties lp = (LinkProperties) callbackObj;
5381 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5382 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5383 }
5384
Chalard Jean0b214af2018-01-12 17:22:49 +09005385 @Test
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005386 public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
5387 final TestNetworkCallback callback = new TestNetworkCallback();
5388 final NetworkRequest request = new NetworkRequest.Builder()
5389 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
5390
5391 mCm.registerNetworkCallback(request, callback);
5392
5393 // Bring up a VPN that specifies an underlying network that does not exist yet.
5394 // Note: it's sort of meaningless for a VPN app to declare a network that doesn't exist yet,
5395 // (and doing so is difficult without using reflection) but it's good to test that the code
5396 // behaves approximately correctly.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005397 mMockVpn.establishForMyUid(false, true, false);
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005398 final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId());
Lorenzo Colittia2e63632020-11-16 16:05:44 +09005399 mService.setUnderlyingNetworksForVpn(new Network[]{wifiNetwork});
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005400 callback.expectAvailableCallbacksUnvalidated(mMockVpn);
5401 assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005402 .hasTransport(TRANSPORT_VPN));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005403 assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005404 .hasTransport(TRANSPORT_WIFI));
5405
5406 // Make that underlying network connect, and expect to see its capabilities immediately
5407 // reflected in the VPN's capabilities.
5408 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5409 assertEquals(wifiNetwork, mWiFiNetworkAgent.getNetwork());
5410 mWiFiNetworkAgent.connect(false);
Lorenzo Colittia2e63632020-11-16 16:05:44 +09005411 // TODO: the callback for the VPN happens before any callbacks are called for the wifi
5412 // network that has just connected. There appear to be two issues here:
5413 // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities() for
5414 // it returns non-null (which happens very early, during handleRegisterNetworkAgent).
5415 // This is not correct because that that point the network is not connected and cannot
5416 // pass any traffic.
5417 // 2. When a network connects, updateNetworkInfo propagates underlying network capabilities
5418 // before rematching networks.
5419 // Given that this scenario can't really happen, this is probably fine for now.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005420 callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
Lorenzo Colittia2e63632020-11-16 16:05:44 +09005421 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005422 assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005423 .hasTransport(TRANSPORT_VPN));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005424 assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005425 .hasTransport(TRANSPORT_WIFI));
5426
5427 // Disconnect the network, and expect to see the VPN capabilities change accordingly.
5428 mWiFiNetworkAgent.disconnect();
5429 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005430 callback.expectCapabilitiesThat(mMockVpn, (nc) ->
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005431 nc.getTransportTypes().length == 1 && nc.hasTransport(TRANSPORT_VPN));
5432
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005433 mMockVpn.disconnect();
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005434 mCm.unregisterNetworkCallback(callback);
5435 }
5436
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005437 private void assertGetNetworkInfoOfGetActiveNetworkIsConnected(boolean expectedConnectivity) {
5438 // What Chromium used to do before https://chromium-review.googlesource.com/2605304
5439 assertEquals("Unexpected result for getActiveNetworkInfo(getActiveNetwork())",
5440 expectedConnectivity, mCm.getNetworkInfo(mCm.getActiveNetwork()).isConnected());
5441 }
5442
5443 @Test
5444 public void testVpnUnderlyingNetworkSuspended() throws Exception {
5445 final TestNetworkCallback callback = new TestNetworkCallback();
5446 mCm.registerDefaultNetworkCallback(callback);
5447
5448 // Connect a VPN.
5449 mMockVpn.establishForMyUid(false, true, false);
5450 callback.expectAvailableCallbacksUnvalidated(mMockVpn);
5451
5452 // Connect cellular data.
5453 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5454 mCellNetworkAgent.connect(false /* validated */);
5455 callback.expectCapabilitiesThat(mMockVpn,
5456 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
5457 && nc.hasTransport(TRANSPORT_CELLULAR));
5458 callback.assertNoCallback();
5459
5460 assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
5461 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5462 assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
5463 assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
5464 assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
5465 assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
5466 assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
5467
5468 // Suspend the cellular network and expect the VPN to be suspended.
5469 mCellNetworkAgent.suspend();
5470 callback.expectCapabilitiesThat(mMockVpn,
5471 nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
5472 && nc.hasTransport(TRANSPORT_CELLULAR));
5473 callback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
5474 callback.assertNoCallback();
5475
5476 assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
5477 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5478 assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
5479 assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
5480 assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
5481 assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
5482 // VPN's main underlying network is suspended, so no connectivity.
5483 assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
5484
5485 // Switch to another network. The VPN should no longer be suspended.
5486 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5487 mWiFiNetworkAgent.connect(false /* validated */);
5488 callback.expectCapabilitiesThat(mMockVpn,
5489 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
5490 && nc.hasTransport(TRANSPORT_WIFI));
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005491 callback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005492 callback.assertNoCallback();
5493
5494 assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
5495 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5496 assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
5497 assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005498 assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005499 assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005500 assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005501
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005502 // Unsuspend cellular and then switch back to it. The VPN remains not suspended.
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005503 mCellNetworkAgent.resume();
5504 mWiFiNetworkAgent.disconnect();
5505 callback.expectCapabilitiesThat(mMockVpn,
5506 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
5507 && nc.hasTransport(TRANSPORT_CELLULAR));
5508 // Spurious double callback?
5509 callback.expectCapabilitiesThat(mMockVpn,
5510 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
5511 && nc.hasTransport(TRANSPORT_CELLULAR));
5512 callback.assertNoCallback();
5513
5514 assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
5515 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5516 assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
5517 assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005518 assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
Lorenzo Colitti7825bc92021-01-12 00:34:44 +09005519 assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005520 assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005521
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005522 // Suspend cellular and expect no connectivity.
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005523 mCellNetworkAgent.suspend();
Lorenzo Colitti7825bc92021-01-12 00:34:44 +09005524 callback.expectCapabilitiesThat(mMockVpn,
5525 nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
5526 && nc.hasTransport(TRANSPORT_CELLULAR));
5527 callback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
5528 callback.assertNoCallback();
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005529
Lorenzo Colitti7825bc92021-01-12 00:34:44 +09005530 assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
5531 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005532 assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
5533 assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
5534 assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED);
Lorenzo Colitti7825bc92021-01-12 00:34:44 +09005535 assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED);
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005536 assertGetNetworkInfoOfGetActiveNetworkIsConnected(false);
5537
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005538 // Resume cellular and expect that connectivity comes back.
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005539 mCellNetworkAgent.resume();
Lorenzo Colitti7825bc92021-01-12 00:34:44 +09005540 callback.expectCapabilitiesThat(mMockVpn,
5541 nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
5542 && nc.hasTransport(TRANSPORT_CELLULAR));
5543 callback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
5544 callback.assertNoCallback();
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005545
5546 assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
5547 .hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5548 assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
5549 assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
Lorenzo Colitti7825bc92021-01-12 00:34:44 +09005550 assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
5551 assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
5552 assertGetNetworkInfoOfGetActiveNetworkIsConnected(true);
Lorenzo Colittid31ccb12021-01-07 23:33:18 +09005553 }
5554
Lorenzo Colitti590e2962020-11-16 10:11:12 +09005555 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005556 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09005557 final int uid = Process.myUid();
5558
5559 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005560 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005561 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5562 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005563 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005564 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5565 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5566 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005567 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5568 .addTransportType(TRANSPORT_WIFI).build();
5569 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005570 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005571 .addTransportType(TRANSPORT_VPN).build();
5572 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005573 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005574 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5575 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005576 mCm.registerDefaultNetworkCallback(defaultCallback);
5577 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005578
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005579 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09005580 mWiFiNetworkAgent.connect(false);
5581
5582 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005583 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005584 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005585 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005586 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005587 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005588
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005589 final Set<UidRange> ranges = uidRangesForUid(uid);
5590 mMockVpn.registerAgent(ranges);
Lorenzo Colitti515b6d82020-11-19 23:20:55 +09005591 mService.setUnderlyingNetworksForVpn(new Network[0]);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005592
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005593 // VPN networks do not satisfy the default request and are automatically validated
5594 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005595 assertFalse(NetworkMonitorUtils.isValidationRequired(
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005596 mMockVpn.getAgent().getNetworkCapabilities()));
5597 mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005598
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005599 mMockVpn.connect(false);
Chalard Jean0b214af2018-01-12 17:22:49 +09005600
Lorenzo Colitti515b6d82020-11-19 23:20:55 +09005601 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
Chalard Jeanb552c462018-02-21 18:43:54 +09005602 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005603 wifiNetworkCallback.assertNoCallback();
Lorenzo Colitti515b6d82020-11-19 23:20:55 +09005604 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5605 defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005606 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005607
5608 ranges.clear();
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005609 mMockVpn.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005610
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005611 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
Chalard Jeanb552c462018-02-21 18:43:54 +09005612 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005613 wifiNetworkCallback.assertNoCallback();
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005614 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
Chalard Jean0b214af2018-01-12 17:22:49 +09005615
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005616 // TODO : The default network callback should actually get a LOST call here (also see the
5617 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5618 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5619 // can't currently update their UIDs without disconnecting, so this does not matter too
5620 // much, but that is the reason the test here has to check for an update to the
5621 // capabilities instead of the expected LOST then AVAILABLE.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005622 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005623
Chalard Jean0b214af2018-01-12 17:22:49 +09005624 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005625 mMockVpn.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005626
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005627 genericNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
Chalard Jeanb552c462018-02-21 18:43:54 +09005628 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005629 wifiNetworkCallback.assertNoCallback();
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005630 vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005631 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5632 // happen outside of the test, ConnectivityService does not rematch callbacks.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005633 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
Chalard Jean0b214af2018-01-12 17:22:49 +09005634
5635 mWiFiNetworkAgent.disconnect();
5636
Chalard Jean059c4262019-09-30 17:51:12 +09005637 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5638 genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5639 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005640 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005641 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005642
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005643 mMockVpn.disconnect();
Chalard Jean0b214af2018-01-12 17:22:49 +09005644
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005645 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
Chalard Jeanb552c462018-02-21 18:43:54 +09005646 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005647 wifiNetworkCallback.assertNoCallback();
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005648 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
5649 defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005650 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005651
5652 mCm.unregisterNetworkCallback(genericNetworkCallback);
5653 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5654 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005655 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005656 }
Chalard Jean26400492018-04-18 20:18:38 +09005657
5658 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005659 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09005660 final int uid = Process.myUid();
5661
5662 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5663 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005664
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005665 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09005666 mWiFiNetworkAgent.connect(true);
5667
5668 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5669 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5670
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005671 mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
lucaslin783f2212019-10-22 18:27:33 +08005672 false /* isStrictMode */);
Chalard Jean26400492018-04-18 20:18:38 +09005673
5674 defaultCallback.assertNoCallback();
5675 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5676
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005677 mMockVpn.disconnect();
Chalard Jean26400492018-04-18 20:18:38 +09005678 defaultCallback.assertNoCallback();
5679
Varun Anand4fa80e82019-02-06 10:13:38 -08005680 mCm.unregisterNetworkCallback(defaultCallback);
5681 }
5682
5683 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005684 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005685 final int uid = Process.myUid();
5686
5687 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5688 mCm.registerDefaultNetworkCallback(defaultCallback);
5689
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005690 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005691 mWiFiNetworkAgent.connect(true);
5692
5693 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5694 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5695
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005696 mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
lucaslin783f2212019-10-22 18:27:33 +08005697 false /* isStrictMode */);
Varun Anand4fa80e82019-02-06 10:13:38 -08005698
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005699 defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
Chalard Jean26400492018-04-18 20:18:38 +09005700 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5701
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005702 mMockVpn.disconnect();
5703 defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
Chalard Jean26400492018-04-18 20:18:38 +09005704 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5705
Chalard Jean26400492018-04-18 20:18:38 +09005706 mCm.unregisterNetworkCallback(defaultCallback);
5707 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005708
5709 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005710 public void testVpnUnvalidated() throws Exception {
5711 final TestNetworkCallback callback = new TestNetworkCallback();
5712 mCm.registerDefaultNetworkCallback(callback);
5713
5714 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005715 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005716 mEthernetNetworkAgent.connect(true);
5717 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5718 callback.assertNoCallback();
5719
5720 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005721 mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
lucaslin783f2212019-10-22 18:27:33 +08005722 false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005723
5724 // Even though the VPN is unvalidated, it becomes the default network for our app.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005725 callback.expectAvailableCallbacksUnvalidated(mMockVpn);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005726 callback.assertNoCallback();
5727
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005728 assertTrue(mMockVpn.getAgent().getScore() > mEthernetNetworkAgent.getScore());
5729 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, mMockVpn.getAgent().getScore());
5730 assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005731
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005732 NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005733 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5734 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5735
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005736 assertFalse(NetworkMonitorUtils.isValidationRequired(
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005737 mMockVpn.getAgent().getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005738 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005739 mMockVpn.getAgent().getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005740
5741 // Pretend that the VPN network validates.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005742 mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
5743 mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005744 // Expect to see the validated capability, but no other changes, because the VPN is already
5745 // the default network for the app.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005746 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mMockVpn);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005747 callback.assertNoCallback();
5748
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005749 mMockVpn.disconnect();
5750 callback.expectCallback(CallbackEntry.LOST, mMockVpn);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005751 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5752 }
5753
5754 @Test
Chalard Jean8e53c792020-05-11 04:59:35 +00005755 public void testVpnStartsWithUnderlyingCaps() throws Exception {
5756 final int uid = Process.myUid();
5757
5758 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5759 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5760 .removeCapability(NET_CAPABILITY_NOT_VPN)
5761 .addTransportType(TRANSPORT_VPN)
5762 .build();
5763 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5764 vpnNetworkCallback.assertNoCallback();
5765
5766 // Connect cell. It will become the default network, and in the absence of setting
5767 // underlying networks explicitly it will become the sole underlying network for the vpn.
5768 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5769 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
5770 mCellNetworkAgent.connect(true);
5771
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005772 mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
Chalard Jean8e53c792020-05-11 04:59:35 +00005773 false /* isStrictMode */);
5774
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005775 vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
Chalard Jean8e53c792020-05-11 04:59:35 +00005776 false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005777 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn.getNetwork(), TIMEOUT_MS,
Chalard Jean8e53c792020-05-11 04:59:35 +00005778 nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED));
5779
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005780 final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
Chalard Jean8e53c792020-05-11 04:59:35 +00005781 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5782 assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
5783 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5784 assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5785 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5786 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
5787 }
5788
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005789 private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
5790 final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
5791 userId, "com.android.calling.package");
5792 final String defaultCapsString = Arrays.toString(defaultCaps);
5793 assertEquals(defaultCapsString, defaultCaps.length, networks.length);
5794 final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
5795 for (NetworkAgentWrapper network : networks) {
5796 final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
5797 final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
5798 assertTrue(msg, defaultCapsSet.contains(nc));
5799 }
5800 }
5801
Chalard Jean8e53c792020-05-11 04:59:35 +00005802 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005803 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005804 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5805 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5806 .removeCapability(NET_CAPABILITY_NOT_VPN)
5807 .addTransportType(TRANSPORT_VPN)
5808 .build();
5809 NetworkCapabilities nc;
5810 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5811 vpnNetworkCallback.assertNoCallback();
5812
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005813 mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
lucaslin783f2212019-10-22 18:27:33 +08005814 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005815
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005816 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5817 nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005818 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5819 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5820 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5821 // For safety reasons a VPN without underlying networks is considered metered.
5822 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
Treehugger Robotcbb1fd02020-05-15 07:14:29 +00005823 // A VPN without underlying networks is not suspended.
5824 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005825
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005826 final int userId = UserHandle.getUserId(Process.myUid());
5827 assertDefaultNetworkCapabilities(userId /* no networks */);
5828
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005829 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005830 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean8e53c792020-05-11 04:59:35 +00005831 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005832 mCellNetworkAgent.connect(true);
5833
5834 mService.setUnderlyingNetworksForVpn(
5835 new Network[] { mCellNetworkAgent.getNetwork() });
5836
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005837 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09005838 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005839 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean8e53c792020-05-11 04:59:35 +00005840 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5841 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005842 assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005843
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005844 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005845 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
Chalard Jean8e53c792020-05-11 04:59:35 +00005846 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005847 mWiFiNetworkAgent.connect(true);
5848
5849 mService.setUnderlyingNetworksForVpn(
5850 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5851
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005852 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09005853 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005854 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean8e53c792020-05-11 04:59:35 +00005855 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5856 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005857 assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005858
5859 // Don't disconnect, but note the VPN is not using wifi any more.
5860 mService.setUnderlyingNetworksForVpn(
5861 new Network[] { mCellNetworkAgent.getNetwork() });
5862
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005863 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09005864 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005865 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean8e53c792020-05-11 04:59:35 +00005866 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5867 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005868 // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
5869 // network (wifi) as well as the underlying networks (cell).
5870 assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005871
Chalard Jean8e53c792020-05-11 04:59:35 +00005872 // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
5873 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005874 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean8e53c792020-05-11 04:59:35 +00005875 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5876 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5877 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5878 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005879 vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
Chalard Jean8e53c792020-05-11 04:59:35 +00005880
5881 // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
5882 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005883 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean8e53c792020-05-11 04:59:35 +00005884 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5885 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
5886 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5887 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005888 vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
Chalard Jean8e53c792020-05-11 04:59:35 +00005889
5890 // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005891 mService.setUnderlyingNetworksForVpn(
5892 new Network[] { mWiFiNetworkAgent.getNetwork() });
5893
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005894 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09005895 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005896 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean8e53c792020-05-11 04:59:35 +00005897 && caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5898 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005899 assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005900
5901 // Use both again.
5902 mService.setUnderlyingNetworksForVpn(
5903 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5904
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005905 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09005906 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005907 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean8e53c792020-05-11 04:59:35 +00005908 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5909 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005910 assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
Chalard Jean8e53c792020-05-11 04:59:35 +00005911
5912 // Cell is suspended again. As WiFi is not, this should not cause a callback.
5913 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
5914 vpnNetworkCallback.assertNoCallback();
5915
5916 // Stop using WiFi. The VPN is suspended again.
5917 mService.setUnderlyingNetworksForVpn(
5918 new Network[] { mCellNetworkAgent.getNetwork() });
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005919 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean8e53c792020-05-11 04:59:35 +00005920 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5921 && caps.hasTransport(TRANSPORT_CELLULAR)
5922 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5923 && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005924 vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005925 assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
Chalard Jean8e53c792020-05-11 04:59:35 +00005926
5927 // Use both again.
5928 mService.setUnderlyingNetworksForVpn(
5929 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5930
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005931 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean8e53c792020-05-11 04:59:35 +00005932 (caps) -> caps.hasTransport(TRANSPORT_VPN)
5933 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
5934 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
5935 && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
Lorenzo Colittib9a8d8e2021-01-11 22:27:57 +09005936 vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005937 assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005938
Chalard Jean6b65ec72018-05-18 22:02:56 +09005939 // Disconnect cell. Receive update without even removing the dead network from the
5940 // underlying networks – it's dead anyway. Not metered any more.
5941 mCellNetworkAgent.disconnect();
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005942 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09005943 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005944 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005945 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005946 assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005947
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005948 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005949 mWiFiNetworkAgent.disconnect();
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005950 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09005951 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005952 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005953 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Lorenzo Colitti503245d2020-12-15 00:45:30 +09005954 // When a network disconnects, the callbacks are fired before all state is updated, so for a
5955 // short time, synchronous calls will behave as if the network is still connected. Wait for
5956 // things to settle.
5957 waitForIdle();
5958 assertDefaultNetworkCapabilities(userId /* no networks */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005959
5960 mMockVpn.disconnect();
5961 }
junyulai4a192e22018-06-13 15:00:37 +08005962
Mike Yuf9729752018-08-17 15:22:05 +08005963 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005964 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005965 final int uid = Process.myUid();
5966
5967 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5968 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5969 .removeCapability(NET_CAPABILITY_NOT_VPN)
5970 .addTransportType(TRANSPORT_VPN)
5971 .build();
5972 NetworkCapabilities nc;
5973 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5974 vpnNetworkCallback.assertNoCallback();
5975
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005976 mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
lucaslin783f2212019-10-22 18:27:33 +08005977 false /* isStrictMode */);
Varun Anand4fa80e82019-02-06 10:13:38 -08005978
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005979 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
5980 nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
Varun Anand4fa80e82019-02-06 10:13:38 -08005981 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5982 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5983 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5984 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5985 // In case of no default network, VPN is considered metered.
5986 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5987
5988 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005989 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005990 mCellNetworkAgent.connect(true);
5991
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09005992 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09005993 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005994 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005995 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005996
5997 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005998 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005999 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6000 mWiFiNetworkAgent.connect(true);
6001
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006002 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09006003 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08006004 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09006005 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08006006
6007 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
6008 // the capabilities.
6009 mCellNetworkAgent.disconnect();
6010
6011 // Disconnect wifi too. Now we have no default network.
6012 mWiFiNetworkAgent.disconnect();
6013
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006014 vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
Chalard Jean6f4216f2019-06-05 01:40:32 +09006015 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08006016 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09006017 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08006018
6019 mMockVpn.disconnect();
6020 }
6021
6022 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006023 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08006024 // Returns true by default when no network is available.
6025 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006026 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08006027 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6028 mWiFiNetworkAgent.connect(true);
6029 waitForIdle();
6030
6031 assertFalse(mCm.isActiveNetworkMetered());
6032 }
6033
6034 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006035 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08006036 // Returns true by default when no network is available.
6037 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006038 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08006039 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
6040 mCellNetworkAgent.connect(true);
6041 waitForIdle();
6042
6043 assertTrue(mCm.isActiveNetworkMetered());
6044 }
6045
6046 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006047 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08006048 // Returns true by default when no network is available.
6049 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006050 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08006051 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
6052 mCellNetworkAgent.connect(true);
6053 waitForIdle();
6054 assertTrue(mCm.isActiveNetworkMetered());
6055
6056 // Connect VPN network. By default it is using current default network (Cell).
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006057 mMockVpn.establishForMyUid();
6058
Varun Anandc51b06d2019-02-25 17:22:02 -08006059 // Ensure VPN is now the active network.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006060 assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
Varun Anandc51b06d2019-02-25 17:22:02 -08006061
6062 // Expect VPN to be metered.
6063 assertTrue(mCm.isActiveNetworkMetered());
6064
6065 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006066 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08006067 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6068 mWiFiNetworkAgent.connect(true);
6069 waitForIdle();
6070 // VPN should still be the active network.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006071 assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
Varun Anandc51b06d2019-02-25 17:22:02 -08006072
6073 // Expect VPN to be unmetered as it should now be using WiFi (new default).
6074 assertFalse(mCm.isActiveNetworkMetered());
6075
6076 // Disconnecting Cell should not affect VPN's meteredness.
6077 mCellNetworkAgent.disconnect();
6078 waitForIdle();
6079
6080 assertFalse(mCm.isActiveNetworkMetered());
6081
6082 // Disconnect WiFi; Now there is no platform default network.
6083 mWiFiNetworkAgent.disconnect();
6084 waitForIdle();
6085
6086 // VPN without any underlying networks is treated as metered.
6087 assertTrue(mCm.isActiveNetworkMetered());
6088
Varun Anandc51b06d2019-02-25 17:22:02 -08006089 mMockVpn.disconnect();
6090 }
6091
6092 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006093 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08006094 // Returns true by default when no network is available.
6095 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006096 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08006097 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
6098 mCellNetworkAgent.connect(true);
6099 waitForIdle();
6100 assertTrue(mCm.isActiveNetworkMetered());
6101
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006102 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08006103 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6104 mWiFiNetworkAgent.connect(true);
6105 waitForIdle();
6106 assertFalse(mCm.isActiveNetworkMetered());
6107
6108 // Connect VPN network.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006109 mMockVpn.establishForMyUid();
6110
Varun Anandc51b06d2019-02-25 17:22:02 -08006111 // Ensure VPN is now the active network.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006112 assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
Varun Anandc51b06d2019-02-25 17:22:02 -08006113 // VPN is using Cell
6114 mService.setUnderlyingNetworksForVpn(
6115 new Network[] { mCellNetworkAgent.getNetwork() });
6116 waitForIdle();
6117
6118 // Expect VPN to be metered.
6119 assertTrue(mCm.isActiveNetworkMetered());
6120
6121 // VPN is now using WiFi
6122 mService.setUnderlyingNetworksForVpn(
6123 new Network[] { mWiFiNetworkAgent.getNetwork() });
6124 waitForIdle();
6125
6126 // Expect VPN to be unmetered
6127 assertFalse(mCm.isActiveNetworkMetered());
6128
6129 // VPN is using Cell | WiFi.
6130 mService.setUnderlyingNetworksForVpn(
6131 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
6132 waitForIdle();
6133
6134 // Expect VPN to be metered.
6135 assertTrue(mCm.isActiveNetworkMetered());
6136
6137 // VPN is using WiFi | Cell.
6138 mService.setUnderlyingNetworksForVpn(
6139 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
6140 waitForIdle();
6141
6142 // Order should not matter and VPN should still be metered.
6143 assertTrue(mCm.isActiveNetworkMetered());
6144
6145 // VPN is not using any underlying networks.
6146 mService.setUnderlyingNetworksForVpn(new Network[0]);
6147 waitForIdle();
6148
6149 // VPN without underlying networks is treated as metered.
6150 assertTrue(mCm.isActiveNetworkMetered());
6151
Varun Anandc51b06d2019-02-25 17:22:02 -08006152 mMockVpn.disconnect();
6153 }
6154
6155 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006156 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08006157 // Returns true by default when no network is available.
6158 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006159 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08006160 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6161 mWiFiNetworkAgent.connect(true);
6162 waitForIdle();
6163 assertFalse(mCm.isActiveNetworkMetered());
6164
6165 // Connect VPN network.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006166 mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUid(Process.myUid()),
6167 new LinkProperties());
6168 mMockVpn.connect(true);
Varun Anandc51b06d2019-02-25 17:22:02 -08006169 waitForIdle();
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006170 assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
Varun Anandc51b06d2019-02-25 17:22:02 -08006171
6172 // VPN is tracking current platform default (WiFi).
6173 mService.setUnderlyingNetworksForVpn(null);
6174 waitForIdle();
6175
6176 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
6177 assertTrue(mCm.isActiveNetworkMetered());
6178
6179 // VPN explicitly declares WiFi as its underlying network.
6180 mService.setUnderlyingNetworksForVpn(
6181 new Network[] { mWiFiNetworkAgent.getNetwork() });
6182 waitForIdle();
6183
6184 // Doesn't really matter whether VPN declares its underlying networks explicitly.
6185 assertTrue(mCm.isActiveNetworkMetered());
6186
6187 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
6188 // anyways suppose to be metered.
6189 mWiFiNetworkAgent.disconnect();
6190 waitForIdle();
6191
6192 assertTrue(mCm.isActiveNetworkMetered());
6193
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006194 mMockVpn.disconnect();
Varun Anandc51b06d2019-02-25 17:22:02 -08006195 }
6196
6197 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006198 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08006199 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
6200 final NetworkRequest cellRequest = new NetworkRequest.Builder()
6201 .addTransportType(TRANSPORT_CELLULAR)
6202 .build();
6203 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
6204
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006205 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08006206 mCellNetworkAgent.connect(true);
6207 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6208
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006209 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08006210 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
6211
6212 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006213 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08006214 cellNetworkCallback.assertNoCallback();
6215
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006216 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08006217 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
6218
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006219 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08006220 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
6221
6222 // Restrict the network based on UID rule and NOT_METERED capability change.
6223 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6224 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
6225 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
6226 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
6227 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
6228 mCellNetworkAgent);
6229 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006230 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08006231 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
6232
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006233 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08006234 cellNetworkCallback.assertNoCallback();
6235
6236 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006237 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08006238 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006239 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08006240 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006241 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08006242 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
6243 cellNetworkCallback.assertNoCallback();
6244
6245 mCm.unregisterNetworkCallback(cellNetworkCallback);
6246 }
6247
6248 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006249 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08006250 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
6251 mCm.registerDefaultNetworkCallback(defaultCallback);
6252
6253 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006254 setUidRulesChanged(RULE_REJECT_ALL);
6255 setUidRulesChanged(RULE_NONE);
6256 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08006257 defaultCallback.assertNoCallback();
6258
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006259 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08006260 mCellNetworkAgent.connect(true);
6261 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
6262 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
6263
6264 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006265 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08006266 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6267 mWiFiNetworkAgent.connect(true);
6268 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
6269
6270 // Switch to METERED network. Restrict the use of the network.
6271 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006272 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08006273 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
6274
6275 // Network becomes NOT_METERED.
6276 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
6277 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
6278 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
6279
6280 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006281 setRestrictBackgroundChanged(true);
6282 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08006283 defaultCallback.assertNoCallback();
6284
6285 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006286 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08006287 defaultCallback.assertNoCallback();
6288
6289 mCm.unregisterNetworkCallback(defaultCallback);
6290 }
6291
Lorenzo Colitti1cfd6b62021-01-28 18:31:31 +09006292 private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
6293 assertNotNull(ni);
6294 assertEquals(type, ni.getType());
6295 assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
6296 }
6297
6298 private void assertActiveNetworkInfo(int type, DetailedState state) {
6299 checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
6300 }
6301 private void assertNetworkInfo(int type, DetailedState state) {
6302 checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
6303 }
6304
Chalard Jean143124b2019-12-03 22:13:37 +09006305 @Test
6306 public final void testLoseTrusted() throws Exception {
6307 final NetworkRequest trustedRequest = new NetworkRequest.Builder()
6308 .addCapability(NET_CAPABILITY_TRUSTED)
6309 .build();
6310 final TestNetworkCallback trustedCallback = new TestNetworkCallback();
6311 mCm.requestNetwork(trustedRequest, trustedCallback);
6312
6313 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6314 mCellNetworkAgent.connect(true);
6315 trustedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6316 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09006317 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09006318
6319 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6320 mWiFiNetworkAgent.connect(true);
Chalard Jean10c8d542020-02-20 07:32:12 +00006321 trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean143124b2019-12-03 22:13:37 +09006322 verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09006323 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09006324
6325 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
Chalard Jean143124b2019-12-03 22:13:37 +09006326 trustedCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
6327 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09006328 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09006329
6330 mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
6331 trustedCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
6332 verify(mNetworkManagementService).clearDefaultNetId();
6333
6334 mCm.unregisterNetworkCallback(trustedCallback);
6335 }
6336
Chalard Jeanb6ec0762019-12-03 16:12:33 +09006337 @Ignore // 40%+ flakiness : figure out why and re-enable.
Chalard Jean587758b2019-11-29 16:41:50 +09006338 @Test
6339 public final void testBatteryStatsNetworkType() throws Exception {
6340 final LinkProperties cellLp = new LinkProperties();
6341 cellLp.setInterfaceName("cell0");
6342 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
6343 mCellNetworkAgent.connect(true);
6344 waitForIdle();
6345 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
6346 TYPE_MOBILE);
6347 reset(mBatteryStatsService);
6348
6349 final LinkProperties wifiLp = new LinkProperties();
6350 wifiLp.setInterfaceName("wifi0");
6351 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
6352 mWiFiNetworkAgent.connect(true);
6353 waitForIdle();
6354 verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(),
6355 TYPE_WIFI);
6356 reset(mBatteryStatsService);
6357
Chalard Jean587758b2019-11-29 16:41:50 +09006358 mCellNetworkAgent.disconnect();
6359
6360 cellLp.setInterfaceName("wifi0");
6361 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
6362 mCellNetworkAgent.connect(true);
6363 waitForIdle();
6364 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
6365 TYPE_MOBILE);
6366 }
6367
junyulai4a192e22018-06-13 15:00:37 +08006368 /**
6369 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
6370 */
6371 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
6372 InterfaceConfiguration cfg = new InterfaceConfiguration();
6373 cfg.setHardwareAddress("11:22:33:44:55:66");
6374 cfg.setLinkAddress(la);
6375 return cfg;
6376 }
6377
6378 /**
6379 * Make expected stack link properties, copied from Nat464Xlat.
6380 */
6381 private LinkProperties makeClatLinkProperties(LinkAddress la) {
6382 LinkAddress clatAddress = la;
6383 LinkProperties stacked = new LinkProperties();
6384 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
6385 RouteInfo ipv4Default = new RouteInfo(
6386 new LinkAddress(Inet4Address.ANY, 0),
6387 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
6388 stacked.addRoute(ipv4Default);
6389 stacked.addLinkAddress(clatAddress);
6390 return stacked;
6391 }
6392
6393 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006394 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08006395 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
6396 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006397 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
6398 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
Lorenzo Colitti756273e2020-04-16 16:49:33 +00006399 final String kOtherNat64PrefixString = "64:ff9b::";
6400 final IpPrefix kOtherNat64Prefix = new IpPrefix(
6401 InetAddress.getByName(kOtherNat64PrefixString), 96);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006402 final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(),
6403 MOBILE_IFNAME);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006404 final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
6405 final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006406 final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(),
6407 CLAT_PREFIX + MOBILE_IFNAME);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006408
junyulai4a192e22018-06-13 15:00:37 +08006409 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6410 .addTransportType(TRANSPORT_CELLULAR)
6411 .addCapability(NET_CAPABILITY_INTERNET)
6412 .build();
6413 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6414 mCm.registerNetworkCallback(networkRequest, networkCallback);
6415
Lorenzo Colittid593e292019-02-19 13:21:56 +09006416 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08006417 final LinkProperties cellLp = new LinkProperties();
6418 cellLp.setInterfaceName(MOBILE_IFNAME);
6419 cellLp.addLinkAddress(myIpv6);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006420 cellLp.addRoute(defaultRoute);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006421 cellLp.addRoute(ipv6Subnet);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09006422 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
junyulai4a192e22018-06-13 15:00:37 +08006423 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006424 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08006425 reset(mMockNetd);
Chalard Jean587758b2019-11-29 16:41:50 +09006426 reset(mBatteryStatsService);
junyulai4a192e22018-06-13 15:00:37 +08006427
Lorenzo Colittid593e292019-02-19 13:21:56 +09006428 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08006429 mCellNetworkAgent.connect(true);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09006430 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
Chalard Jean587758b2019-11-29 16:41:50 +09006431 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08006432
6433 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006434 assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute);
Luke Huanga24d5d82019-04-09 18:41:49 +08006435 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
Chalard Jean587758b2019-11-29 16:41:50 +09006436 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
6437 TYPE_MOBILE);
Luke Huanga24d5d82019-04-09 18:41:49 +08006438
junyulai4a192e22018-06-13 15:00:37 +08006439 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006440 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006441
Lorenzo Colittid593e292019-02-19 13:21:56 +09006442 // Switching default network updates TCP buffer sizes.
6443 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6444
6445 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
6446 // the NAT64 prefix was removed because one was never discovered.
6447 cellLp.addLinkAddress(myIpv4);
6448 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006449 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006450 assertRoutesAdded(cellNetId, ipv4Subnet);
Luke Huang65914772019-03-16 00:31:46 +08006451 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08006452 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006453
Chalard Jean587758b2019-11-29 16:41:50 +09006454 // Make sure BatteryStats was not told about any v4- interfaces, as none should have
6455 // come online yet.
6456 waitForIdle();
6457 verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt());
6458
Lorenzo Colittid593e292019-02-19 13:21:56 +09006459 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006460 verifyNoMoreInteractions(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006461 reset(mNetworkManagementService);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006462 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006463 reset(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006464 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6465 .thenReturn(getClatInterfaceConfig(myIpv4));
Lorenzo Colittid593e292019-02-19 13:21:56 +09006466
6467 // Remove IPv4 address. Expect prefix discovery to be started again.
6468 cellLp.removeLinkAddress(myIpv4);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006469 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006470 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006471 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006472 assertRoutesRemoved(cellNetId, ipv4Subnet);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006473
6474 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006475 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006476 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006477 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6478 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006479 LinkProperties lpBeforeClat = networkCallback.expectCallback(
Chalard Jean059c4262019-09-30 17:51:12 +09006480 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006481 assertEquals(0, lpBeforeClat.getStackedLinks().size());
6482 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
6483 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6484
6485 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08006486 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean059c4262019-09-30 17:51:12 +09006487 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006488 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
6489 .getStackedLinks();
6490 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006491 assertRoutesAdded(cellNetId, stackedDefault);
junyulai4a192e22018-06-13 15:00:37 +08006492
6493 // Change trivial linkproperties and see if stacked link is preserved.
6494 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
6495 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006496 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006497
6498 List<LinkProperties> stackedLpsAfterChange =
6499 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
6500 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
6501 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
6502
Luke Huang65914772019-03-16 00:31:46 +08006503 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08006504 mResolverParamsParcelCaptor.capture());
6505 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6506 assertEquals(1, resolvrParams.servers.length);
6507 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08006508
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09006509 for (final LinkProperties stackedLp : stackedLpsAfterChange) {
6510 verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(),
6511 TYPE_MOBILE);
6512 }
Lorenzo Colittid86407b2020-03-18 07:52:25 +00006513 reset(mMockNetd);
Chalard Jean587758b2019-11-29 16:41:50 +09006514
Lorenzo Colitti756273e2020-04-16 16:49:33 +00006515 // Change the NAT64 prefix without first removing it.
6516 // Expect clatd to be stopped and started with the new prefix.
6517 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6518 kOtherNat64PrefixString, 96);
6519 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6520 (lp) -> lp.getStackedLinks().size() == 0);
6521 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
6522 assertRoutesRemoved(cellNetId, stackedDefault);
6523
6524 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString());
6525 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6526 (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix));
6527 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
6528 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6529 (lp) -> lp.getStackedLinks().size() == 1);
6530 assertRoutesAdded(cellNetId, stackedDefault);
6531 reset(mMockNetd);
6532
Lorenzo Colittid593e292019-02-19 13:21:56 +09006533 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
6534 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08006535 cellLp.addLinkAddress(myIpv4);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006536 cellLp.addRoute(ipv4Subnet);
junyulai4a192e22018-06-13 15:00:37 +08006537 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006538 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006539 assertRoutesAdded(cellNetId, ipv4Subnet);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09006540 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08006541 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006542
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006543 // As soon as stop is called, the linkproperties lose the stacked interface.
Chalard Jean059c4262019-09-30 17:51:12 +09006544 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006545 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
6546 LinkProperties expected = new LinkProperties(cellLp);
Lorenzo Colitti756273e2020-04-16 16:49:33 +00006547 expected.setNat64Prefix(kOtherNat64Prefix);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006548 assertEquals(expected, actualLpAfterIpv4);
6549 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006550 assertRoutesRemoved(cellNetId, stackedDefault);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006551
6552 // The interface removed callback happens but has no effect after stop is called.
6553 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6554 networkCallback.assertNoCallback();
6555
Lorenzo Colittid593e292019-02-19 13:21:56 +09006556 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006557 verifyNoMoreInteractions(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006558 reset(mNetworkManagementService);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006559 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006560 reset(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006561 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6562 .thenReturn(getClatInterfaceConfig(myIpv4));
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006563
Lorenzo Colittid593e292019-02-19 13:21:56 +09006564 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6565 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
Lorenzo Colitti756273e2020-04-16 16:49:33 +00006566 kOtherNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006567 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6568 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006569
6570 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006571 cellLp.removeLinkAddress(myIpv4);
6572 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6573 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6574 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006575 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006576 assertRoutesRemoved(cellNetId, ipv4Subnet); // Directly-connected routes auto-added.
Luke Huang65914772019-03-16 00:31:46 +08006577 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006578 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6579 kNat64PrefixString, 96);
Chalard Jean059c4262019-09-30 17:51:12 +09006580 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006581 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6582
6583 // Clat iface comes up. Expect stacked link to be added.
6584 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006585 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6586 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006587 assertRoutesAdded(cellNetId, stackedDefault);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006588
6589 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006590 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6591 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006592 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6593 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006594 assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
6595
6596 // Stop has no effect because clat is already stopped.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006597 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006598 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6599 (lp) -> lp.getStackedLinks().size() == 0);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006600 verifyNoMoreInteractions(mMockNetd);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006601
6602 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08006603 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006604 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006605 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08006606 mCm.unregisterNetworkCallback(networkCallback);
6607 }
Chiachang Wanga6093042018-09-28 22:42:48 +08006608
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006609 private void expectNat64PrefixChange(TestableNetworkCallback callback,
6610 TestNetworkAgentWrapper agent, IpPrefix prefix) {
6611 callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix));
6612 }
6613
6614 @Test
6615 public void testNat64PrefixMultipleSources() throws Exception {
6616 final String iface = "wlan0";
6617 final String pref64FromRaStr = "64:ff9b::";
6618 final String pref64FromDnsStr = "2001:db8:64::";
6619 final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96);
6620 final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96);
6621 final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96");
6622
6623 final NetworkRequest request = new NetworkRequest.Builder()
6624 .addCapability(NET_CAPABILITY_INTERNET)
6625 .build();
6626 final TestNetworkCallback callback = new TestNetworkCallback();
6627 mCm.registerNetworkCallback(request, callback);
6628
6629 final LinkProperties baseLp = new LinkProperties();
6630 baseLp.setInterfaceName(iface);
6631 baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
6632 baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464"));
6633
6634 reset(mMockNetd, mMockDnsResolver);
6635 InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
6636
6637 // If a network already has a NAT64 prefix on connect, clatd is started immediately and
6638 // prefix discovery is never started.
6639 LinkProperties lp = new LinkProperties(baseLp);
6640 lp.setNat64Prefix(pref64FromRa);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006641 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
6642 mWiFiNetworkAgent.connect(false);
6643 final Network network = mWiFiNetworkAgent.getNetwork();
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006644 int netId = network.getNetId();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006645 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006646 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006647 inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006648 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6649 callback.assertNoCallback();
6650 assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
6651
6652 // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
6653 lp.setNat64Prefix(null);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006654 mWiFiNetworkAgent.sendLinkProperties(lp);
6655 expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006656 inOrder.verify(mMockNetd).clatdStop(iface);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006657 inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006658 inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
6659
Lorenzo Colitti0d020c62020-04-20 11:38:11 +00006660 // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
6661 // clatd is started with the prefix from the RA.
6662 lp.setNat64Prefix(pref64FromRa);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006663 mWiFiNetworkAgent.sendLinkProperties(lp);
6664 expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
Lorenzo Colitti0d020c62020-04-20 11:38:11 +00006665 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
6666 inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006667 inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
Lorenzo Colitti0d020c62020-04-20 11:38:11 +00006668
6669 // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
6670 // discovery has succeeded.
6671 lp.setNat64Prefix(null);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006672 mWiFiNetworkAgent.sendLinkProperties(lp);
6673 expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
Lorenzo Colitti0d020c62020-04-20 11:38:11 +00006674 inOrder.verify(mMockNetd).clatdStop(iface);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006675 inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
Lorenzo Colitti0d020c62020-04-20 11:38:11 +00006676 inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
6677
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006678 mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
6679 pref64FromDnsStr, 96);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006680 expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006681 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
6682
Lorenzo Colittifbf205a2020-05-24 11:30:55 +00006683 // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
6684 // discovery is not stopped, and there are no callbacks.
6685 lp.setNat64Prefix(pref64FromDns);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006686 mWiFiNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittifbf205a2020-05-24 11:30:55 +00006687 callback.assertNoCallback();
6688 inOrder.verify(mMockNetd, never()).clatdStop(iface);
6689 inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
6690 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6691 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006692 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
Lorenzo Colittifbf205a2020-05-24 11:30:55 +00006693
6694 // If the RA is later withdrawn, nothing happens again.
6695 lp.setNat64Prefix(null);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006696 mWiFiNetworkAgent.sendLinkProperties(lp);
Lorenzo Colittifbf205a2020-05-24 11:30:55 +00006697 callback.assertNoCallback();
6698 inOrder.verify(mMockNetd, never()).clatdStop(iface);
6699 inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
6700 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6701 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006702 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
Lorenzo Colittifbf205a2020-05-24 11:30:55 +00006703
6704 // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006705 lp.setNat64Prefix(pref64FromRa);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006706 mWiFiNetworkAgent.sendLinkProperties(lp);
6707 expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006708 inOrder.verify(mMockNetd).clatdStop(iface);
6709 inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
Lorenzo Colittifbf205a2020-05-24 11:30:55 +00006710
6711 // Stopping prefix discovery results in a prefix removed notification.
6712 mService.mNetdEventCallback.onNat64PrefixEvent(netId, false /* added */,
6713 pref64FromDnsStr, 96);
6714
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006715 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006716 inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006717 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6718
6719 // If the RA prefix changes, clatd is restarted and prefix discovery is not started.
6720 lp.setNat64Prefix(newPref64FromRa);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006721 mWiFiNetworkAgent.sendLinkProperties(lp);
6722 expectNat64PrefixChange(callback, mWiFiNetworkAgent, newPref64FromRa);
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006723 inOrder.verify(mMockNetd).clatdStop(iface);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006724 inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006725 inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString());
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006726 inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString());
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006727 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6728 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6729
6730 // If the RA prefix changes to the same value, nothing happens.
6731 lp.setNat64Prefix(newPref64FromRa);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006732 mWiFiNetworkAgent.sendLinkProperties(lp);
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006733 callback.assertNoCallback();
6734 assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
6735 inOrder.verify(mMockNetd, never()).clatdStop(iface);
6736 inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
6737 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6738 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006739 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006740
6741 // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties.
6742
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006743 // If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
6744 // (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
6745 lp.setNat64Prefix(null);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006746 mWiFiNetworkAgent.sendLinkProperties(lp);
6747 expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006748 inOrder.verify(mMockNetd).clatdStop(iface);
6749 inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
6750 inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
6751 mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
6752 pref64FromDnsStr, 96);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006753 expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006754 inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
6755 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
6756
6757 lp.setNat64Prefix(pref64FromDns);
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006758 mWiFiNetworkAgent.sendLinkProperties(lp);
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006759 callback.assertNoCallback();
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006760 inOrder.verify(mMockNetd, never()).clatdStop(iface);
6761 inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
6762 inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
6763 inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
6764 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
6765
6766 // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
6767 // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
6768 // clat has been stopped, or the test will be flaky.
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006769 ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
6770 mWiFiNetworkAgent.disconnect();
6771 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
6772 b.expectBroadcast();
Lorenzo Colitti7f7171c2020-05-26 10:13:17 +00006773
6774 inOrder.verify(mMockNetd).clatdStop(iface);
6775 inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
6776 inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString());
6777
Lorenzo Colitti1cb345e2020-04-20 11:37:18 +00006778 mCm.unregisterNetworkCallback(callback);
6779 }
6780
Chiachang Wanga6093042018-09-28 22:42:48 +08006781 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006782 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08006783 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6784 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6785 .addCapability(NET_CAPABILITY_INTERNET)
6786 .build();
6787 mCm.registerNetworkCallback(networkRequest, networkCallback);
6788
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006789 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08006790 final LinkProperties cellLp = new LinkProperties();
6791 cellLp.setInterfaceName(MOBILE_IFNAME);
6792 mCellNetworkAgent.sendLinkProperties(cellLp);
6793 reset(mNetworkManagementService);
6794 mCellNetworkAgent.connect(true);
6795 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6796 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6797 eq(ConnectivityManager.TYPE_MOBILE));
6798
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006799 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006800 final LinkProperties wifiLp = new LinkProperties();
6801 wifiLp.setInterfaceName(WIFI_IFNAME);
6802 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6803
6804 // Network switch
6805 reset(mNetworkManagementService);
6806 mWiFiNetworkAgent.connect(true);
6807 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006808 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006809 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6810 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6811 eq(ConnectivityManager.TYPE_WIFI));
6812 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6813
6814 // Disconnect wifi and switch back to cell
6815 reset(mNetworkManagementService);
6816 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006817 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006818 assertNoCallbacks(networkCallback);
6819 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6820 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6821 eq(ConnectivityManager.TYPE_MOBILE));
6822
6823 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006824 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006825 wifiLp.setInterfaceName(WIFI_IFNAME);
6826 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6827 mWiFiNetworkAgent.connect(true);
6828 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006829 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006830 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6831
6832 // Disconnect cell
6833 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006834 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006835 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006836 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006837 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6838 // sent as network being switched. Ensure rule removal for cell will not be triggered
6839 // unexpectedly before network being removed.
6840 waitForIdle();
6841 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006842 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6843 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08006844 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006845
6846 // Disconnect wifi
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006847 ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
Chiachang Wanga6093042018-09-28 22:42:48 +08006848 reset(mNetworkManagementService);
6849 mWiFiNetworkAgent.disconnect();
Lorenzo Colittid590e33e2021-01-06 01:36:07 +09006850 b.expectBroadcast();
Chiachang Wanga6093042018-09-28 22:42:48 +08006851 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6852
6853 // Clean up
6854 mCm.unregisterNetworkCallback(networkCallback);
6855 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006856
Chalard Jeane7b24752019-06-20 16:01:19 +09006857 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006858 String[] values = tcpBufferSizes.split(",");
6859 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6860 String wmemValues = String.join(" ", values[3], values[4], values[5]);
Chalard Jeane7b24752019-06-20 16:01:19 +09006861 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006862 reset(mMockNetd);
6863 }
6864
6865 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006866 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006867 final String testTcpBufferSizes = "1,2,3,4,5,6";
paulhu66269b32019-08-30 19:24:36 +08006868 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6869 .addTransportType(TRANSPORT_CELLULAR)
6870 .addCapability(NET_CAPABILITY_INTERNET)
6871 .build();
6872 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6873 mCm.registerNetworkCallback(networkRequest, networkCallback);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006874
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006875 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006876 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006877 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006878 mCellNetworkAgent.connect(false);
paulhu66269b32019-08-30 19:24:36 +08006879 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006880 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6881
6882 // Change link Properties should have updated tcp buffer size.
6883 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006884 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006885 mCellNetworkAgent.sendLinkProperties(lp);
Chalard Jean059c4262019-09-30 17:51:12 +09006886 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006887 verifyTcpBufferSizeChange(testTcpBufferSizes);
paulhu66269b32019-08-30 19:24:36 +08006888
6889 // Clean up.
6890 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006891 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
paulhu66269b32019-08-30 19:24:36 +08006892 networkCallback.assertNoCallback();
6893 mCm.unregisterNetworkCallback(networkCallback);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006894 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006895
6896 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006897 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006898 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006899 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006900 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6901 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6902 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6903 }
6904
6905 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006906 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006907 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006908 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006909 mWiFiNetworkAgent.connect(true);
6910 waitForIdle();
6911 assertNull(mService.getProxyForNetwork(null));
6912
6913 final LinkProperties testLinkProperties = new LinkProperties();
6914 testLinkProperties.setHttpProxy(testProxyInfo);
6915
6916 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6917 waitForIdle();
6918
6919 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6920 }
6921
6922 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006923 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006924 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6925
6926 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006927 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006928 mWiFiNetworkAgent.connect(true);
6929 waitForIdle();
6930 assertNull(mService.getProxyForNetwork(null));
6931
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006932 // Connect a VPN network with a proxy.
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006933 LinkProperties testLinkProperties = new LinkProperties();
6934 testLinkProperties.setHttpProxy(testProxyInfo);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006935 mMockVpn.establishForMyUid(testLinkProperties);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006936
6937 // Test that the VPN network returns a proxy, and the WiFi does not.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006938 assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork()));
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006939 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6940 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6941
6942 // Test that the VPN network returns no proxy when it is set to null.
6943 testLinkProperties.setHttpProxy(null);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006944 mMockVpn.sendLinkProperties(testLinkProperties);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006945 waitForIdle();
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006946 assertNull(mService.getProxyForNetwork(mMockVpn.getNetwork()));
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006947 assertNull(mService.getProxyForNetwork(null));
6948
6949 // Set WiFi proxy and check that the vpn proxy is still null.
6950 testLinkProperties.setHttpProxy(testProxyInfo);
6951 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6952 waitForIdle();
6953 assertNull(mService.getProxyForNetwork(null));
6954
6955 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6956 // correct proxy setting.
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006957 mMockVpn.disconnect();
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006958 waitForIdle();
6959 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6960 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6961 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6962 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006963
6964 @Test
6965 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6966 LinkProperties lp = new LinkProperties();
6967 lp.setInterfaceName("tun0");
6968 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00006969 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006970 // The uid range needs to cover the test app so the network is visible to it.
6971 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006972 mMockVpn.establish(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006973
6974 // Connected VPN should have interface rules set up. There are two expected invocations,
6975 // one during VPN uid update, one during VPN LinkProperties update
6976 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6977 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6978 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6979 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6980 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6981
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006982 mMockVpn.disconnect();
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006983 waitForIdle();
6984
6985 // Disconnected VPN should have interface rules removed
6986 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6987 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6988 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6989 }
6990
6991 @Test
6992 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6993 LinkProperties lp = new LinkProperties();
6994 lp.setInterfaceName("tun0");
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00006995 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006996 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6997 // The uid range needs to cover the test app so the network is visible to it.
6998 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09006999 mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007000
7001 // Legacy VPN should not have interface rules set up
7002 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
7003 }
7004
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09007005 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007006 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
7007 throws Exception {
7008 LinkProperties lp = new LinkProperties();
7009 lp.setInterfaceName("tun0");
7010 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
7011 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
7012 // The uid range needs to cover the test app so the network is visible to it.
7013 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007014 mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007015
7016 // IPv6 unreachable route should not be misinterpreted as a default route
7017 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
7018 }
7019
7020 @Test
7021 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
7022 LinkProperties lp = new LinkProperties();
7023 lp.setInterfaceName("tun0");
7024 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00007025 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007026 // The uid range needs to cover the test app so the network is visible to it.
7027 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007028 mMockVpn.establish(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007029
7030 // Connected VPN should have interface rules set up. There are two expected invocations,
7031 // one during VPN uid update, one during VPN LinkProperties update
7032 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
7033 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
7034 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
7035 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
7036
7037 reset(mMockNetd);
7038 InOrder inOrder = inOrder(mMockNetd);
7039 lp.setInterfaceName("tun1");
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007040 mMockVpn.sendLinkProperties(lp);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007041 waitForIdle();
7042 // VPN handover (switch to a new interface) should result in rules being updated (old rules
7043 // removed first, then new rules added)
7044 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
7045 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
7046 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
7047 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
7048
7049 reset(mMockNetd);
7050 lp = new LinkProperties();
7051 lp.setInterfaceName("tun1");
7052 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007053 mMockVpn.sendLinkProperties(lp);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007054 waitForIdle();
7055 // VPN not routing everything should no longer have interface filtering rules
7056 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
7057 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
7058
7059 reset(mMockNetd);
7060 lp = new LinkProperties();
7061 lp.setInterfaceName("tun1");
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00007062 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007063 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007064 mMockVpn.sendLinkProperties(lp);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007065 waitForIdle();
7066 // Back to routing all IPv6 traffic should have filtering rules
7067 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
7068 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
7069 }
7070
7071 @Test
7072 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
7073 LinkProperties lp = new LinkProperties();
7074 lp.setInterfaceName("tun0");
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00007075 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007076 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
7077 // The uid range needs to cover the test app so the network is visible to it.
7078 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007079 mMockVpn.establish(lp, VPN_UID, Collections.singleton(vpnRange));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007080
7081 reset(mMockNetd);
7082 InOrder inOrder = inOrder(mMockNetd);
7083
7084 // Update to new range which is old range minus APP1, i.e. only APP2
7085 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
7086 new UidRange(vpnRange.start, APP1_UID - 1),
7087 new UidRange(APP1_UID + 1, vpnRange.stop)));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007088 mMockVpn.setUids(newRanges);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007089 waitForIdle();
7090
7091 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
7092 // Verify old rules are removed before new rules are added
7093 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
7094 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
7095 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
7096 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
7097 }
7098
Valentin Iftimec86ebba2019-09-24 13:32:13 +02007099 @Test
7100 public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
7101 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
7102
7103 LinkProperties wifiLp = new LinkProperties();
7104 wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
7105 wifiLp.setWakeOnLanSupported(false);
7106
7107 // Default network switch should update ifaces.
7108 mWiFiNetworkAgent.connect(false);
7109 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
7110 waitForIdle();
7111
7112 // ConnectivityService should have changed the WakeOnLanSupported to true
7113 wifiLp.setWakeOnLanSupported(true);
7114 assertEquals(wifiLp, mService.getActiveLinkProperties());
7115 }
7116
Chiachang Wang4d2791b2020-06-16 01:02:52 +00007117 @Test
7118 public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception {
7119 class TestNetworkAgent extends NetworkAgent {
7120 TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) {
7121 super(context, looper, "MockAgent", new NetworkCapabilities(),
7122 new LinkProperties(), 40 , config, null /* provider */);
7123 }
7124 }
7125 final NetworkAgent naNoExtraInfo = new TestNetworkAgent(
7126 mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig());
7127 naNoExtraInfo.register();
7128 verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any());
7129 naNoExtraInfo.unregister();
7130
7131 reset(mNetworkStack);
7132 final NetworkAgentConfig config =
7133 new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build();
7134 final NetworkAgent naExtraInfo = new TestNetworkAgent(
7135 mServiceContext, mCsHandlerThread.getLooper(), config);
7136 naExtraInfo.register();
7137 verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any());
7138 naExtraInfo.unregister();
7139 }
7140
Qingxi Li9c5d8b92020-01-08 12:51:49 -08007141 private void setupLocationPermissions(
7142 int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
7143 final ApplicationInfo applicationInfo = new ApplicationInfo();
7144 applicationInfo.targetSdkVersion = targetSdk;
7145 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
7146 .thenReturn(applicationInfo);
7147
7148 when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
7149
7150 if (op != null) {
7151 when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
7152 .thenReturn(AppOpsManager.MODE_ALLOWED);
7153 }
7154
7155 if (perm != null) {
7156 mServiceContext.setPermission(perm, PERMISSION_GRANTED);
7157 }
7158 }
7159
7160 private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
7161 final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
7162
7163 return mService
7164 .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
7165 .getOwnerUid();
7166 }
7167
Qingxi Li7cf06622020-01-17 17:54:27 -08007168 @Test
Qingxi Li9c5d8b92020-01-08 12:51:49 -08007169 public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
7170 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
7171 Manifest.permission.ACCESS_FINE_LOCATION);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007172
Qingxi Li9c5d8b92020-01-08 12:51:49 -08007173 final int myUid = Process.myUid();
7174 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
7175 }
Qingxi Li7cf06622020-01-17 17:54:27 -08007176
Qingxi Li9c5d8b92020-01-08 12:51:49 -08007177 @Test
7178 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception {
7179 setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
7180 Manifest.permission.ACCESS_COARSE_LOCATION);
7181
7182 final int myUid = Process.myUid();
7183 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
7184 }
7185
7186 @Test
7187 public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception {
7188 // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
7189 setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
7190 Manifest.permission.ACCESS_FINE_LOCATION);
7191
7192 final int myUid = Process.myUid();
7193 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
7194 }
7195
7196 @Test
7197 public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception {
7198 // Test that even with fine location permission, not being the owner leads to sanitization.
7199 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
7200 Manifest.permission.ACCESS_FINE_LOCATION);
7201
7202 final int myUid = Process.myUid();
7203 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
7204 }
7205
7206 @Test
7207 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception {
7208 // Test that not having fine location permission leads to sanitization.
7209 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
7210 Manifest.permission.ACCESS_COARSE_LOCATION);
7211
7212 // Test that without the location permission, the owner field is sanitized.
7213 final int myUid = Process.myUid();
7214 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
7215 }
7216
7217 @Test
7218 public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception {
7219 setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
7220
7221 // Test that without the location permission, the owner field is sanitized.
7222 final int myUid = Process.myUid();
7223 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
Qingxi Li7cf06622020-01-17 17:54:27 -08007224 }
7225
Benedict Wong5d50ce82020-01-20 22:14:59 -08007226 private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
7227 throws Exception {
7228 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007229 mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
Benedict Wong5d50ce82020-01-20 22:14:59 -08007230 mMockVpn.setVpnType(vpnType);
7231
7232 final VpnInfo vpnInfo = new VpnInfo();
7233 vpnInfo.ownerUid = vpnOwnerUid;
7234 mMockVpn.setVpnInfo(vpnInfo);
7235 }
7236
7237 private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
7238 throws Exception {
7239 setupConnectionOwnerUid(vpnOwnerUid, vpnType);
7240
7241 // Test as VPN app
7242 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7243 mServiceContext.setPermission(
7244 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
7245 }
7246
7247 private ConnectionInfo getTestConnectionInfo() throws Exception {
7248 return new ConnectionInfo(
7249 IPPROTO_TCP,
7250 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
7251 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
7252 }
7253
7254 @Test
7255 public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
7256 final int myUid = Process.myUid();
7257 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
7258
7259 try {
7260 mService.getConnectionOwnerUid(getTestConnectionInfo());
7261 fail("Expected SecurityException for non-VpnService app");
7262 } catch (SecurityException expected) {
7263 }
7264 }
7265
7266 @Test
7267 public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
7268 final int myUid = Process.myUid();
7269 setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
7270
7271 try {
7272 mService.getConnectionOwnerUid(getTestConnectionInfo());
7273 fail("Expected SecurityException for non-VpnService app");
7274 } catch (SecurityException expected) {
7275 }
7276 }
7277
7278 @Test
7279 public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
7280 final int myUid = Process.myUid();
7281 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
7282
7283 // TODO: Test the returned UID
7284 mService.getConnectionOwnerUid(getTestConnectionInfo());
7285 }
7286
7287 @Test
7288 public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
7289 final int myUid = Process.myUid();
7290 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
7291 mServiceContext.setPermission(
7292 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
7293
7294 // TODO: Test the returned UID
7295 mService.getConnectionOwnerUid(getTestConnectionInfo());
7296 }
7297
7298 @Test
7299 public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
7300 throws Exception {
7301 final int myUid = Process.myUid();
7302 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
7303 mServiceContext.setPermission(
7304 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
7305
7306 // TODO: Test the returned UID
7307 mService.getConnectionOwnerUid(getTestConnectionInfo());
7308 }
7309
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007310 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
7311 final PackageInfo packageInfo = new PackageInfo();
paulhu86e23eb2019-11-05 18:05:05 +08007312 if (hasSystemPermission) {
7313 packageInfo.requestedPermissions = new String[] {
7314 CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
7315 packageInfo.requestedPermissionsFlags = new int[] {
7316 REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
7317 } else {
7318 packageInfo.requestedPermissions = new String[0];
7319 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00007320 packageInfo.applicationInfo = new ApplicationInfo();
7321 packageInfo.applicationInfo.privateFlags = 0;
7322 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
7323 UserHandle.getAppId(uid));
7324 return packageInfo;
7325 }
Cody Kesting63e4e002019-12-18 10:57:50 -08007326
7327 @Test
7328 public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
7329 final NetworkRequest request =
7330 new NetworkRequest(
7331 new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
7332 try {
7333 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08007334 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08007335 fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
7336 } catch (IllegalArgumentException expected) {
7337 }
7338 }
7339
Lorenzo Colittid86407b2020-03-18 07:52:25 +00007340 private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
7341 assertEquals(route.getDestination().toString(), parcel.destination);
7342 assertEquals(route.getInterface(), parcel.ifName);
7343 assertEquals(route.getMtu(), parcel.mtu);
7344
7345 switch (route.getType()) {
7346 case RouteInfo.RTN_UNICAST:
7347 if (route.hasGateway()) {
7348 assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
7349 } else {
7350 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
7351 }
7352 break;
7353 case RouteInfo.RTN_UNREACHABLE:
7354 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
7355 break;
7356 case RouteInfo.RTN_THROW:
7357 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
7358 break;
7359 default:
7360 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
7361 break;
7362 }
7363 }
7364
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00007365 private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
Lorenzo Colittid86407b2020-03-18 07:52:25 +00007366 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
7367 verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00007368 for (int i = 0; i < routes.length; i++) {
Lorenzo Colittid86407b2020-03-18 07:52:25 +00007369 assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00007370 }
7371 }
7372
7373 private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
Lorenzo Colittid86407b2020-03-18 07:52:25 +00007374 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
7375 verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
7376 captor.capture());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00007377 for (int i = 0; i < routes.length; i++) {
Lorenzo Colittid86407b2020-03-18 07:52:25 +00007378 assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00007379 }
7380 }
7381
Cody Kesting63e4e002019-12-18 10:57:50 -08007382 @Test
7383 public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
7384 final NetworkRequest wifiRequest =
7385 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
Cody Kesting63e4e002019-12-18 10:57:50 -08007386 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
7387
7388 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08007389 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08007390
Cody Kestinge330fcd2020-01-15 16:31:08 -08007391 // Block until all other events are done processing.
7392 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7393
7394 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
7395 verify(mConnectivityDiagnosticsCallback).asBinder();
Cody Kesting4600fa52020-03-05 10:46:02 -08007396 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
Cody Kesting63e4e002019-12-18 10:57:50 -08007397
7398 mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
7399 verify(mIBinder, timeout(TIMEOUT_MS))
7400 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
Cody Kesting4600fa52020-03-05 10:46:02 -08007401 assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
Cody Kesting63e4e002019-12-18 10:57:50 -08007402 verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
7403 }
7404
7405 @Test
7406 public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
7407 final NetworkRequest wifiRequest =
7408 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
7409 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
7410
7411 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08007412 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08007413
Cody Kestinge330fcd2020-01-15 16:31:08 -08007414 // Block until all other events are done processing.
7415 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7416
7417 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
Cody Kesting63e4e002019-12-18 10:57:50 -08007418 verify(mConnectivityDiagnosticsCallback).asBinder();
Cody Kesting4600fa52020-03-05 10:46:02 -08007419 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
Cody Kesting63e4e002019-12-18 10:57:50 -08007420
7421 // Register the same callback again
7422 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08007423 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08007424
7425 // Block until all other events are done processing.
7426 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7427
Cody Kesting4600fa52020-03-05 10:46:02 -08007428 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
Cody Kesting63e4e002019-12-18 10:57:50 -08007429 }
Cody Kestinga75e26b2020-01-05 14:06:39 -08007430
7431 @Test
7432 public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
7433 final NetworkAgentInfo naiWithoutUid =
7434 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00007435 null, null, null, null, null, new NetworkCapabilities(), 0,
Cody Kesting0d8d6ac2020-05-12 18:47:10 +00007436 mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
Cody Kestinga75e26b2020-01-05 14:06:39 -08007437
7438 mServiceContext.setPermission(
7439 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
7440 assertTrue(
7441 "NetworkStack permission not applied",
7442 mService.checkConnectivityDiagnosticsPermissions(
7443 Process.myPid(), Process.myUid(), naiWithoutUid,
7444 mContext.getOpPackageName()));
7445 }
7446
7447 @Test
Automerger Merge Workera5333b92020-03-16 15:48:50 +00007448 public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
7449 final NetworkAgentInfo naiWithoutUid =
7450 new NetworkAgentInfo(
7451 null, null, null, null, null, new NetworkCapabilities(), 0,
Cody Kesting0d8d6ac2020-05-12 18:47:10 +00007452 mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
Automerger Merge Workera5333b92020-03-16 15:48:50 +00007453
7454 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7455
Automerger Merge Worker69fad4c2020-03-16 20:37:44 +00007456 assertFalse(
7457 "Mismatched uid/package name should not pass the location permission check",
7458 mService.checkConnectivityDiagnosticsPermissions(
7459 Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
7460 mContext.getOpPackageName()));
Automerger Merge Workera5333b92020-03-16 15:48:50 +00007461 }
7462
7463 @Test
Cody Kestinga75e26b2020-01-05 14:06:39 -08007464 public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
7465 final NetworkAgentInfo naiWithoutUid =
7466 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00007467 null, null, null, null, null, new NetworkCapabilities(), 0,
Cody Kesting0d8d6ac2020-05-12 18:47:10 +00007468 mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
Cody Kestinga75e26b2020-01-05 14:06:39 -08007469
7470 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7471
7472 assertFalse(
7473 "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics",
7474 mService.checkConnectivityDiagnosticsPermissions(
7475 Process.myPid(), Process.myUid(), naiWithoutUid,
7476 mContext.getOpPackageName()));
7477 }
7478
7479 @Test
7480 public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
Cody Kesting3096b662020-03-18 21:11:29 +00007481 final Network network = new Network(NET_ID);
Cody Kestinga75e26b2020-01-05 14:06:39 -08007482 final NetworkAgentInfo naiWithoutUid =
7483 new NetworkAgentInfo(
Cody Kesting3096b662020-03-18 21:11:29 +00007484 null, null, network, null, null, new NetworkCapabilities(), 0,
Cody Kesting0d8d6ac2020-05-12 18:47:10 +00007485 mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
Cody Kestinga75e26b2020-01-05 14:06:39 -08007486
7487 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
7488 Manifest.permission.ACCESS_FINE_LOCATION);
Cody Kestinga75e26b2020-01-05 14:06:39 -08007489
7490 // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be
7491 // active
7492 final VpnInfo info = new VpnInfo();
7493 info.ownerUid = Process.myUid();
Lorenzo Colittia2e63632020-11-16 16:05:44 +09007494 info.vpnIface = VPN_IFNAME;
Cody Kestinga75e26b2020-01-05 14:06:39 -08007495 mMockVpn.setVpnInfo(info);
Lorenzo Colittia2e63632020-11-16 16:05:44 +09007496
Lorenzo Colittiabb9e372020-11-18 22:50:57 +09007497 mMockVpn.establishForMyUid();
7498 waitForIdle();
7499
7500 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7501
Lorenzo Colittia2e63632020-11-16 16:05:44 +09007502
7503 assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {network}));
Cody Kestinga75e26b2020-01-05 14:06:39 -08007504 assertTrue(
7505 "Active VPN permission not applied",
7506 mService.checkConnectivityDiagnosticsPermissions(
7507 Process.myPid(), Process.myUid(), naiWithoutUid,
7508 mContext.getOpPackageName()));
Cody Kesting3096b662020-03-18 21:11:29 +00007509
Lorenzo Colittia2e63632020-11-16 16:05:44 +09007510 assertTrue(mService.setUnderlyingNetworksForVpn(null));
Cody Kesting3096b662020-03-18 21:11:29 +00007511 assertFalse(
7512 "VPN shouldn't receive callback on non-underlying network",
7513 mService.checkConnectivityDiagnosticsPermissions(
7514 Process.myPid(), Process.myUid(), naiWithoutUid,
7515 mContext.getOpPackageName()));
Cody Kestinga75e26b2020-01-05 14:06:39 -08007516 }
7517
7518 @Test
7519 public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
7520 final NetworkCapabilities nc = new NetworkCapabilities();
Cody Kestingf7ac9962020-03-16 18:15:28 -07007521 nc.setAdministratorUids(new int[] {Process.myUid()});
Cody Kestinga75e26b2020-01-05 14:06:39 -08007522 final NetworkAgentInfo naiWithUid =
7523 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00007524 null, null, null, null, null, nc, 0, mServiceContext, null, null,
Cody Kesting0d8d6ac2020-05-12 18:47:10 +00007525 mService, null, null, null, 0, INVALID_UID);
Cody Kestinga75e26b2020-01-05 14:06:39 -08007526
7527 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
7528 Manifest.permission.ACCESS_FINE_LOCATION);
7529 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7530
Cody Kestinga75e26b2020-01-05 14:06:39 -08007531 assertTrue(
7532 "NetworkCapabilities administrator uid permission not applied",
7533 mService.checkConnectivityDiagnosticsPermissions(
7534 Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
7535 }
7536
7537 @Test
7538 public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
7539 final NetworkCapabilities nc = new NetworkCapabilities();
7540 nc.setOwnerUid(Process.myUid());
Cody Kestingf7ac9962020-03-16 18:15:28 -07007541 nc.setAdministratorUids(new int[] {Process.myUid()});
Cody Kestinga75e26b2020-01-05 14:06:39 -08007542 final NetworkAgentInfo naiWithUid =
7543 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00007544 null, null, null, null, null, nc, 0, mServiceContext, null, null,
Cody Kesting0d8d6ac2020-05-12 18:47:10 +00007545 mService, null, null, null, 0, INVALID_UID);
Cody Kestinga75e26b2020-01-05 14:06:39 -08007546
7547 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
7548 Manifest.permission.ACCESS_FINE_LOCATION);
7549 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
7550
7551 // Use wrong pid and uid
7552 assertFalse(
7553 "Permissions allowed when they shouldn't be granted",
7554 mService.checkConnectivityDiagnosticsPermissions(
7555 Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
7556 mContext.getOpPackageName()));
7557 }
7558
Cody Kesting560eb262020-02-12 14:50:58 -08007559 @Test
7560 public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
7561 throws Exception {
7562 // Set up the Network, which leads to a ConnectivityReport being cached for the network.
7563 final TestNetworkCallback callback = new TestNetworkCallback();
7564 mCm.registerDefaultNetworkCallback(callback);
7565 final LinkProperties linkProperties = new LinkProperties();
7566 linkProperties.setInterfaceName(INTERFACE_NAME);
7567 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
7568 mCellNetworkAgent.connect(true);
7569 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
7570 callback.assertNoCallback();
7571
7572 final NetworkRequest request = new NetworkRequest.Builder().build();
7573 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
7574
7575 mServiceContext.setPermission(
7576 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
7577
7578 mService.registerConnectivityDiagnosticsCallback(
7579 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
7580
7581 // Block until all other events are done processing.
7582 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7583
7584 verify(mConnectivityDiagnosticsCallback)
7585 .onConnectivityReportAvailable(argThat(report -> {
7586 return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
7587 && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
7588 }));
7589 }
7590
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007591 private void setUpConnectivityDiagnosticsCallback() throws Exception {
Cody Kestinga75e26b2020-01-05 14:06:39 -08007592 final NetworkRequest request = new NetworkRequest.Builder().build();
7593 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
7594
7595 mServiceContext.setPermission(
7596 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
7597
7598 mService.registerConnectivityDiagnosticsCallback(
7599 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
7600
7601 // Block until all other events are done processing.
7602 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7603
7604 // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
7605 final TestNetworkCallback callback = new TestNetworkCallback();
7606 mCm.registerDefaultNetworkCallback(callback);
7607 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7608 mCellNetworkAgent.connect(true);
7609 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
7610 callback.assertNoCallback();
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007611 }
7612
7613 @Test
Cody Kesting9347e332020-03-05 15:19:48 -08007614 public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable()
7615 throws Exception {
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007616 setUpConnectivityDiagnosticsCallback();
Cody Kestinga75e26b2020-01-05 14:06:39 -08007617
Cody Kestinge330fcd2020-01-15 16:31:08 -08007618 // Block until all other events are done processing.
7619 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7620
7621 // Verify onConnectivityReport fired
Cody Kesting9347e332020-03-05 15:19:48 -08007622 verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable(
Cody Kestinga3b71c42020-02-11 10:03:26 -08007623 argThat(report -> {
7624 final NetworkCapabilities nc = report.getNetworkCapabilities();
7625 return nc.getUids() == null
Cody Kestingf7ac9962020-03-16 18:15:28 -07007626 && nc.getAdministratorUids().length == 0
Cody Kestinga3b71c42020-02-11 10:03:26 -08007627 && nc.getOwnerUid() == Process.INVALID_UID;
7628 }));
Cody Kestinga75e26b2020-01-05 14:06:39 -08007629 }
Cody Kesting4f49f142020-01-06 16:55:35 -08007630
7631 @Test
7632 public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007633 setUpConnectivityDiagnosticsCallback();
Cody Kesting4f49f142020-01-06 16:55:35 -08007634
7635 // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
7636 // cellular network agent
7637 mCellNetworkAgent.notifyDataStallSuspected();
7638
Cody Kestinge330fcd2020-01-15 16:31:08 -08007639 // Block until all other events are done processing.
7640 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7641
7642 // Verify onDataStallSuspected fired
Cody Kestinga3b71c42020-02-11 10:03:26 -08007643 verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(
7644 argThat(report -> {
7645 final NetworkCapabilities nc = report.getNetworkCapabilities();
7646 return nc.getUids() == null
Cody Kestingf7ac9962020-03-16 18:15:28 -07007647 && nc.getAdministratorUids().length == 0
Cody Kestinga3b71c42020-02-11 10:03:26 -08007648 && nc.getOwnerUid() == Process.INVALID_UID;
7649 }));
Cody Kesting4f49f142020-01-06 16:55:35 -08007650 }
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007651
7652 @Test
7653 public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
7654 setUpConnectivityDiagnosticsCallback();
7655
7656 final Network n = mCellNetworkAgent.getNetwork();
7657 final boolean hasConnectivity = true;
7658 mService.reportNetworkConnectivity(n, hasConnectivity);
7659
Cody Kestinge330fcd2020-01-15 16:31:08 -08007660 // Block until all other events are done processing.
7661 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7662
7663 // Verify onNetworkConnectivityReported fired
7664 verify(mConnectivityDiagnosticsCallback)
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007665 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
7666
7667 final boolean noConnectivity = false;
7668 mService.reportNetworkConnectivity(n, noConnectivity);
7669
Cody Kestinge330fcd2020-01-15 16:31:08 -08007670 // Block until all other events are done processing.
7671 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7672
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007673 // Wait for onNetworkConnectivityReported to fire
Cody Kestinge330fcd2020-01-15 16:31:08 -08007674 verify(mConnectivityDiagnosticsCallback)
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007675 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
7676 }
Lorenzo Colittid86407b2020-03-18 07:52:25 +00007677
7678 @Test
7679 public void testRouteAddDeleteUpdate() throws Exception {
7680 final NetworkRequest request = new NetworkRequest.Builder().build();
7681 final TestNetworkCallback networkCallback = new TestNetworkCallback();
7682 mCm.registerNetworkCallback(request, networkCallback);
7683 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7684 reset(mMockNetd);
7685 mCellNetworkAgent.connect(false);
7686 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
7687 final int netId = mCellNetworkAgent.getNetwork().netId;
7688
7689 final String iface = "rmnet_data0";
7690 final InetAddress gateway = InetAddress.getByName("fe80::5678");
7691 RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
7692 RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
7693 RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
7694 RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
7695 RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
7696 1280 /* mtu */);
7697
7698 // Send LinkProperties and check that we ask netd to add routes.
7699 LinkProperties lp = new LinkProperties();
7700 lp.setInterfaceName(iface);
7701 lp.addRoute(direct);
7702 lp.addRoute(rio1);
7703 lp.addRoute(defaultRoute);
7704 mCellNetworkAgent.sendLinkProperties(lp);
7705 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3);
7706
7707 assertRoutesAdded(netId, direct, rio1, defaultRoute);
7708 reset(mMockNetd);
7709
7710 // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
7711 assertTrue(lp.getRoutes().contains(defaultRoute));
7712 lp.removeRoute(rio1);
7713 lp.addRoute(rio2);
7714 lp.addRoute(defaultWithMtu);
7715 // Ensure adding the same route with a different MTU replaces the previous route.
7716 assertFalse(lp.getRoutes().contains(defaultRoute));
7717 assertTrue(lp.getRoutes().contains(defaultWithMtu));
7718
7719 mCellNetworkAgent.sendLinkProperties(lp);
7720 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
7721 x -> x.getRoutes().contains(rio2));
7722
7723 assertRoutesRemoved(netId, rio1);
7724 assertRoutesAdded(netId, rio2);
7725
7726 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
7727 verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
7728 assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
7729
7730
7731 mCm.unregisterNetworkCallback(networkCallback);
7732 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07007733}