blob: b864e37f9ed0135dd2c2622f157576c4c1baca25 [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;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070039import static android.net.ConnectivityManager.TYPE_WIFI;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080040import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
41import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
42import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
43import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
lucaslin783f2212019-10-22 18:27:33 +080044import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080045import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
46import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060047import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
48import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
52import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
53import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
54import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
55import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
57import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
58import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090059import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060060import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080061import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060062import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
63import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
64import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
65import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
66import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
67import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
68import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
69import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090070import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060071import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
72import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080073import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
74import static android.net.NetworkPolicyManager.RULE_NONE;
75import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
76import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000077import static android.net.RouteInfo.RTN_UNREACHABLE;
Benedict Wong5d50ce82020-01-20 22:14:59 -080078import static android.system.OsConstants.IPPROTO_TCP;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060079
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090080import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090081import static com.android.testutils.ConcurrentUtilsKt.await;
82import static com.android.testutils.ConcurrentUtilsKt.durationOf;
Chalard Jeane7b24752019-06-20 16:01:19 +090083import static com.android.testutils.ExceptionUtils.ignoreExceptions;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090084import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
85import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
86import static com.android.testutils.MiscAssertsKt.assertEmpty;
87import static com.android.testutils.MiscAssertsKt.assertLength;
88import static com.android.testutils.MiscAssertsKt.assertRunsInAtMost;
89import static com.android.testutils.MiscAssertsKt.assertThrows;
90
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090091import static org.junit.Assert.assertEquals;
92import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080093import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090094import static org.junit.Assert.assertNotNull;
95import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060096import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090097import static org.junit.Assert.fail;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090098import static org.mockito.ArgumentMatchers.anyLong;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090099import static org.mockito.ArgumentMatchers.anyString;
Cody Kestinga3b71c42020-02-11 10:03:26 -0800100import static org.mockito.ArgumentMatchers.argThat;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000101import static org.mockito.ArgumentMatchers.eq;
Chalard Jean587758b2019-11-29 16:41:50 +0900102import static org.mockito.ArgumentMatchers.startsWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900103import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +0900104import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600105import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900106import static org.mockito.Mockito.doAnswer;
107import static org.mockito.Mockito.doNothing;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900108import static org.mockito.Mockito.doReturn;
Roshan Piuse38acab2020-01-16 12:17:17 -0800109import static org.mockito.Mockito.doThrow;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000110import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -0800111import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600112import static org.mockito.Mockito.never;
113import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900114import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900115import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +0900116import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600117import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -0700118import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900119import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700120
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900121import android.Manifest;
junyulai7c469172019-01-16 20:23:34 +0800122import android.annotation.NonNull;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900123import android.app.AlarmManager;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800124import android.app.AppOpsManager;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900125import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400126import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400127import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900128import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900129import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700130import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400131import android.content.Intent;
132import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000133import android.content.pm.ApplicationInfo;
134import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100135import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000136import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900137import android.content.res.Resources;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800138import android.location.LocationManager;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900139import android.net.CaptivePortalData;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800140import android.net.ConnectionInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400141import android.net.ConnectivityManager;
142import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900143import android.net.ConnectivityManager.PacketKeepalive;
144import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900145import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900146import android.net.ConnectivityThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800147import android.net.IConnectivityDiagnosticsCallback;
Luke Huang65914772019-03-16 00:31:46 +0800148import android.net.IDnsResolver;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900149import android.net.IIpConnectivityMetrics;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800150import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900151import android.net.INetworkMonitor;
152import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800153import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700154import android.net.INetworkPolicyManager;
155import android.net.INetworkStatsService;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800156import android.net.InetAddresses;
junyulai4a192e22018-06-13 15:00:37 +0800157import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900158import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800159import android.net.IpSecManager;
160import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900161import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700162import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700163import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400164import android.net.Network;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400165import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700166import android.net.NetworkFactory;
Chalard Jean9ca13772019-11-15 12:08:36 +0900167import android.net.NetworkInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400168import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700169import android.net.NetworkSpecifier;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900170import android.net.NetworkStack;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900171import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800172import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100173import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000174import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800175import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700176import android.net.RouteInfo;
Lorenzo Colittid86407b2020-03-18 07:52:25 +0000177import android.net.RouteInfoParcel;
junyulai48eac1d42018-12-27 17:25:29 +0800178import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900179import android.net.UidRange;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900180import android.net.Uri;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800181import android.net.VpnManager;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900182import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900183import android.net.shared.NetworkMonitorUtils;
184import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900185import android.net.util.MultinetworkPolicyTracker;
Chalard Jean751bb3f2019-06-19 23:29:58 +0900186import android.os.BadParcelableException;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100187import android.os.Binder;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800188import android.os.Build;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900189import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400190import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700191import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700192import android.os.HandlerThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800193import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700194import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900195import android.os.Looper;
Etan Cohena7434272017-04-03 12:17:51 -0700196import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800197import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700198import android.os.Parcelable;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800199import android.os.PersistableBundle;
Robin Leed2baf792016-03-24 12:07:00 +0000200import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800201import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900202import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900203import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000204import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900205import android.provider.Settings;
Benedict Wongb570e862020-01-17 19:33:55 -0800206import android.security.KeyStore;
junyulai0c666972019-03-04 22:45:36 +0800207import android.system.Os;
Hall Liued6d6e62020-03-26 19:09:30 -0700208import android.telephony.TelephonyManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900209import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800210import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100211import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700212import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800213import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700214
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800215import androidx.test.InstrumentationRegistry;
Guang Zhub90866d2019-09-01 21:37:04 -0700216import androidx.test.filters.FlakyTest;
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800217import androidx.test.filters.SmallTest;
218import androidx.test.runner.AndroidJUnit4;
219
Chalard Jean587758b2019-11-29 16:41:50 +0900220import com.android.internal.app.IBatteryStats;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900221import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800222import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900223import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900224import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900225import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900226import com.android.internal.util.test.FakeSettingsProvider;
Cody Kesting63e4e002019-12-18 10:57:50 -0800227import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
Chalard Jeandda156a2018-01-10 21:19:32 +0900228import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900229import com.android.server.connectivity.DefaultNetworkMetrics;
230import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900231import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800232import com.android.server.connectivity.Nat464Xlat;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800233import com.android.server.connectivity.NetworkAgentInfo;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900234import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000235import com.android.server.connectivity.ProxyTracker;
Chalard Jeandda156a2018-01-10 21:19:32 +0900236import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900237import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900238import com.android.server.net.NetworkPolicyManagerInternal;
Chalard Jeane7b24752019-06-20 16:01:19 +0900239import com.android.testutils.ExceptionUtils;
Chalard Jeance75e0e2019-05-28 16:48:32 +0900240import com.android.testutils.HandlerUtilsKt;
Chalard Jean059c4262019-09-30 17:51:12 +0900241import com.android.testutils.RecorderCallback.CallbackEntry;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900242import com.android.testutils.TestableNetworkCallback;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400243
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900244import org.junit.After;
245import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900246import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900247import org.junit.Test;
248import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900249import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000250import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900251import org.mockito.Mock;
252import org.mockito.MockitoAnnotations;
253import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900254import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900255
junyulai0c666972019-03-04 22:45:36 +0800256import java.io.IOException;
257import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800258import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000259import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700260import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900261import java.net.InetSocketAddress;
262import java.net.Socket;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400263import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900264import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100265import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800266import java.util.Collections;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900267import java.util.HashMap;
dalyk1fcb7392018-03-05 12:42:22 -0500268import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100269import java.util.List;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900270import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100271import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900272import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800273import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800274import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800275import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900276import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900277import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700278import java.util.concurrent.atomic.AtomicBoolean;
Chalard Jean9ca13772019-11-15 12:08:36 +0900279import java.util.function.Predicate;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800280import java.util.function.Supplier;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900281
282import kotlin.reflect.KClass;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700283
284/**
285 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400286 *
287 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900288 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700289 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900290@RunWith(AndroidJUnit4.class)
291@SmallTest
292public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700293 private static final String TAG = "ConnectivityServiceTest";
294
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900295 private static final int TIMEOUT_MS = 500;
Chalard Jeanb299b842019-09-27 17:13:14 +0900296 private static final int TEST_LINGER_DELAY_MS = 300;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900297 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
298 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
299 // timeout. For this, our assertions should run fast enough to leave less than
300 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
301 // supposedly fired, and the time we call expectCallback.
Chalard Jeanb299b842019-09-27 17:13:14 +0900302 private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900303 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
304 // complete before callbacks are verified.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900305 private static final int TEST_REQUEST_TIMEOUT_MS = 150;
306
307 private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900308
Cody Kestinga75e26b2020-01-05 14:06:39 -0800309 private static final long TIMESTAMP = 1234L;
310
Cody Kesting3096b662020-03-18 21:11:29 +0000311 private static final int NET_ID = 110;
312
junyulai4a192e22018-06-13 15:00:37 +0800313 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700314 private static final String MOBILE_IFNAME = "test_rmnet_data0";
315 private static final String WIFI_IFNAME = "test_wlan0";
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200316 private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
Roshan Piuse38acab2020-01-16 12:17:17 -0800317 private static final String TEST_PACKAGE_NAME = "com.android.test.package";
Luke Huang65914772019-03-16 00:31:46 +0800318 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700319
Cody Kesting560eb262020-02-12 14:50:58 -0800320 private static final String INTERFACE_NAME = "interface";
321
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900322 private MockContext mServiceContext;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900323 private HandlerThread mCsHandlerThread;
324 private ConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900325 private WrappedConnectivityManager mCm;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900326 private TestNetworkAgentWrapper mWiFiNetworkAgent;
327 private TestNetworkAgentWrapper mCellNetworkAgent;
328 private TestNetworkAgentWrapper mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900329 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900330 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800331 private INetworkPolicyListener mPolicyListener;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900332 private WrappedMultinetworkPolicyTracker mPolicyTracker;
333 private HandlerThread mAlarmManagerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700334
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900335 @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
Hugo Benichi64901e52017-10-19 14:42:40 +0900336 @Mock IpConnectivityMetrics.Logger mMetricsService;
337 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900338 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600339 @Mock INetworkStatsService mStatsService;
Chalard Jean587758b2019-11-29 16:41:50 +0900340 @Mock IBatteryStats mBatteryStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800341 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800342 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800343 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900344 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100345 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000346 @Mock UserManager mUserManager;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900347 @Mock NotificationManager mNotificationManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900348 @Mock AlarmManager mAlarmManager;
Cody Kesting63e4e002019-12-18 10:57:50 -0800349 @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
350 @Mock IBinder mIBinder;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800351 @Mock LocationManager mLocationManager;
352 @Mock AppOpsManager mAppOpsManager;
Hall Liued6d6e62020-03-26 19:09:30 -0700353 @Mock TelephonyManager mTelephonyManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900354
waynema13516842019-03-12 18:13:49 +0800355 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
356 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900357
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900358 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
359 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
360 // reflect the state of our test ConnectivityService.
361 private class WrappedConnectivityManager extends ConnectivityManager {
362 private Network mFakeBoundNetwork;
363
364 public synchronized boolean bindProcessToNetwork(Network network) {
365 mFakeBoundNetwork = network;
366 return true;
367 }
368
369 public synchronized Network getBoundNetworkForProcess() {
370 return mFakeBoundNetwork;
371 }
372
373 public WrappedConnectivityManager(Context context, ConnectivityService service) {
374 super(context, service);
375 }
376 }
377
Paul Jensend7b6ca92015-05-13 14:05:12 -0400378 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900379 private final MockContentResolver mContentResolver;
Chalard Jean9ca13772019-11-15 12:08:36 +0900380 // Contains all registered receivers since this object was created. Useful to clear
381 // them when needed, as BroadcastInterceptingContext does not provide this facility.
382 private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>();
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900383
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900384 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900385 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900386 // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
387 private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900388
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900389 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400390 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900391
392 mResources = spy(base.getResources());
393 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
394 thenReturn(new String[] {
395 "wifi,1,1,1,-1,true",
396 "mobile,0,0,0,-1,true",
397 "mobile_mms,2,0,2,60000,true",
Chalard Jean9ca13772019-11-15 12:08:36 +0900398 "mobile_supl,3,0,2,60000,true",
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900399 });
400
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200401 when(mResources.getStringArray(
402 com.android.internal.R.array.config_wakeonlan_supported_interfaces))
403 .thenReturn(new String[]{
404 WIFI_WOL_IFNAME,
405 });
406
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900407 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900408 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400409 }
410
411 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900412 public void startActivityAsUser(Intent intent, UserHandle handle) {
413 mStartedActivities.offer(intent);
414 }
415
Chalard Jeanf30d1e12019-06-27 08:24:51 +0000416 public Intent expectStartActivityIntent(int timeoutMs) {
417 Intent intent = null;
418 try {
419 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
420 } catch (InterruptedException e) {}
421 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
422 return intent;
423 }
424
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900425 public void expectNoStartActivityIntent(int timeoutMs) {
426 try {
427 assertNull("Received unexpected Intent to start activity",
428 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
429 } catch (InterruptedException e) {}
430 }
431
432 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900433 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900434 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900435 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000436 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900437 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800438 if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
439 if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
Hall Liued6d6e62020-03-26 19:09:30 -0700440 if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400441 return super.getSystemService(name);
442 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900443
444 @Override
445 public ContentResolver getContentResolver() {
446 return mContentResolver;
447 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900448
449 @Override
450 public Resources getResources() {
451 return mResources;
452 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100453
454 @Override
455 public PackageManager getPackageManager() {
456 return mPackageManager;
457 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900458
Benedict Wong5d50ce82020-01-20 22:14:59 -0800459 private int checkMockedPermission(String permission, Supplier<Integer> ifAbsent) {
460 final Integer granted = mMockedPermissions.get(permission);
461 return granted != null ? granted : ifAbsent.get();
462 }
463
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900464 @Override
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900465 public int checkPermission(String permission, int pid, int uid) {
Benedict Wong5d50ce82020-01-20 22:14:59 -0800466 return checkMockedPermission(
467 permission, () -> super.checkPermission(permission, pid, uid));
468 }
469
470 @Override
471 public int checkCallingOrSelfPermission(String permission) {
472 return checkMockedPermission(
473 permission, () -> super.checkCallingOrSelfPermission(permission));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900474 }
475
476 @Override
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900477 public void enforceCallingOrSelfPermission(String permission, String message) {
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900478 final Integer granted = mMockedPermissions.get(permission);
479 if (granted == null) {
480 super.enforceCallingOrSelfPermission(permission, message);
481 return;
482 }
483
484 if (!granted.equals(PERMISSION_GRANTED)) {
485 throw new SecurityException("[Test] permission denied: " + permission);
486 }
487 }
488
489 /**
490 * Mock checks for the specified permission, and have them behave as per {@code granted}.
491 *
492 * <p>Passing null reverts to default behavior, which does a real permission check on the
493 * test package.
494 * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
495 * {@link PackageManager#PERMISSION_DENIED}.
496 */
497 public void setPermission(String permission, Integer granted) {
498 mMockedPermissions.put(permission, granted);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900499 }
Chalard Jean9ca13772019-11-15 12:08:36 +0900500
501 @Override
502 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
503 mRegisteredReceivers.add(receiver);
504 return super.registerReceiver(receiver, filter);
505 }
506
507 public void clearRegisteredReceivers() {
508 // super.unregisterReceiver is a no-op for receivers that are not registered (because
509 // they haven't been registered or because they have already been unregistered).
510 // For the same reason, don't bother clearing mRegisteredReceivers.
511 for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv);
512 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900513 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400514
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900515 private void waitForIdle() {
516 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
517 waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
518 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
519 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
520 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
521 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Hugo Benichibb91c572017-05-22 10:44:02 +0900522 }
523
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900524 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900525 if (agent == null) {
526 return;
527 }
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900528 agent.waitForIdle(timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900529 }
530
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900531 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +0900532 public void testWaitForIdle() throws Exception {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900533 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
534
535 // Tests that waitForIdle returns immediately if the service is already idle.
536 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900537 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900538 }
539
540 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900541 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900542 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900543 mWiFiNetworkAgent.connect(false);
544 waitFor(cv);
545 Network n = mWiFiNetworkAgent.getNetwork();
546 assertNotNull(n);
547
548 // Tests that calling waitForIdle waits for messages to be processed.
549 for (int i = 0; i < attempts; i++) {
550 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900551 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900552 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
553 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900554 }
555
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900556 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
557 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800558 @Ignore
Chalard Jeane7b24752019-06-20 16:01:19 +0900559 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900560 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900561 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900562 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Hugo Benichi5d540d12016-10-17 15:54:51 +0900563 mWiFiNetworkAgent.connect(false);
564 waitFor(cv);
565 Network n = mWiFiNetworkAgent.getNetwork();
566 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900567
568 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900569 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900570 for (int i = 0; i < attempts; i++) {
571 mWiFiNetworkAgent.setSignalStrength(i);
572 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
573 // We hit a race condition, as expected. Pass the test.
574 return;
575 }
576 }
577
578 // No race? There is a bug in this test.
579 fail("expected race condition at least once in " + attempts + " attempts");
580 }
581
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900582 private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800583 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
584 | NETWORK_VALIDATION_PROBE_HTTP
585 | NETWORK_VALIDATION_PROBE_HTTPS;
586 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
587 | NETWORK_VALIDATION_RESULT_VALID;
588 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
589 | NETWORK_VALIDATION_PROBE_FALLBACK
590 | NETWORK_VALIDATION_RESULT_PARTIAL;
591 private static final int VALIDATION_RESULT_INVALID = 0;
592
Cody Kesting4f49f142020-01-06 16:55:35 -0800593 private static final long DATA_STALL_TIMESTAMP = 10L;
594 private static final int DATA_STALL_DETECTION_METHOD = 1;
595
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900596 private INetworkMonitor mNetworkMonitor;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900597 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800598 private int mNmValidationResult = VALIDATION_RESULT_BASE;
lucaslin783f2212019-10-22 18:27:33 +0800599 private int mProbesCompleted;
600 private int mProbesSucceeded;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900601 private String mNmValidationRedirectUrl = null;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800602 private PersistableBundle mValidationExtras = PersistableBundle.EMPTY;
Cody Kesting4f49f142020-01-06 16:55:35 -0800603 private PersistableBundle mDataStallExtras = PersistableBundle.EMPTY;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900604 private boolean mNmProvNotificationRequested = false;
605
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900606 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
607 // Contains the redirectUrl from networkStatus(). Before reading, wait for
608 // mNetworkStatusReceived.
609 private String mRedirectUrl;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900610
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900611 TestNetworkAgentWrapper(int transport) throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100612 this(transport, new LinkProperties());
613 }
614
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900615 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
616 throws Exception {
617 super(transport, linkProperties, mServiceContext);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900618
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900619 // Waits for the NetworkAgent to be registered, which includes the creation of the
620 // NetworkMonitor.
621 waitForIdle(TIMEOUT_MS);
Chalard Jean3da8e0f2019-09-20 17:19:31 +0900622 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
623 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900624 }
625
626 @Override
627 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
628 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900629 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900630
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900631 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900632 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900633 return null;
634 };
635
Chalard Jeane7b24752019-06-20 16:01:19 +0900636 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
637 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900638
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900639 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900640 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
641 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
642 doNothing().when(mNetworkStack).makeNetworkMonitor(
643 nmNetworkCaptor.capture(),
644 any() /* name */,
645 nmCbCaptor.capture());
646
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900647 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400648 @Override
649 public void networkStatus(int status, String redirectUrl) {
650 mRedirectUrl = redirectUrl;
651 mNetworkStatusReceived.open();
652 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400653 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900654
Chalard Jean29c6e0c2020-01-16 17:13:26 +0900655 assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900656 mNmCallbacks = nmCbCaptor.getValue();
657
Chalard Jeane7b24752019-06-20 16:01:19 +0900658 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900659
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900660 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900661 }
662
Chalard Jeane7b24752019-06-20 16:01:19 +0900663 private void onValidationRequested() throws Exception {
664 if (mNmProvNotificationRequested
665 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
666 mNmCallbacks.hideProvisioningNotification();
667 mNmProvNotificationRequested = false;
668 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900669
lucaslin783f2212019-10-22 18:27:33 +0800670 mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
Cody Kestinga75e26b2020-01-05 14:06:39 -0800671 mNmCallbacks.notifyNetworkTestedWithExtras(
672 mNmValidationResult, mNmValidationRedirectUrl, TIMESTAMP, mValidationExtras);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900673
Chalard Jeane7b24752019-06-20 16:01:19 +0900674 if (mNmValidationRedirectUrl != null) {
675 mNmCallbacks.showProvisioningNotification(
Roshan Piuse38acab2020-01-16 12:17:17 -0800676 "test_provisioning_notif_action", TEST_PACKAGE_NAME);
Chalard Jeane7b24752019-06-20 16:01:19 +0900677 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900678 }
Paul Jensen3d911462015-06-12 06:40:24 -0400679 }
680
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900681 /**
682 * Connect without adding any internet capability.
683 */
Paul Jensene0988542015-06-25 15:30:08 -0400684 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900685 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400686 }
687
Paul Jensend7b6ca92015-05-13 14:05:12 -0400688 /**
Paul Jensene0988542015-06-25 15:30:08 -0400689 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400690 * @param validated Indicate if network should pretend to be validated.
691 */
692 public void connect(boolean validated) {
lucaslin783f2212019-10-22 18:27:33 +0800693 connect(validated, true, false /* isStrictMode */);
Hugo Benichi16f0a942017-06-20 14:07:59 +0900694 }
695
696 /**
697 * Transition this NetworkAgent to CONNECTED state.
698 * @param validated Indicate if network should pretend to be validated.
699 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
700 */
lucaslin783f2212019-10-22 18:27:33 +0800701 public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900702 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400703
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900704 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400705 final ConditionVariable validatedCv = new ConditionVariable();
706 if (validated) {
lucaslin783f2212019-10-22 18:27:33 +0800707 setNetworkValid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400708 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900709 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900710 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400711 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900712 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400713 public void onCapabilitiesChanged(Network network,
714 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400715 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900716 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400717 validatedCv.open();
718 }
719 }
720 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400721 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400722 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900723 if (hasInternet) {
724 addCapability(NET_CAPABILITY_INTERNET);
725 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400726
Paul Jensene0988542015-06-25 15:30:08 -0400727 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400728
729 if (validated) {
730 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400731 waitFor(validatedCv);
lucaslin783f2212019-10-22 18:27:33 +0800732 setNetworkInvalid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400733 }
734
735 if (callback != null) mCm.unregisterNetworkCallback(callback);
736 }
737
lucaslin783f2212019-10-22 18:27:33 +0800738 public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
739 setNetworkPortal(redirectUrl, isStrictMode);
740 connect(false, true /* hasInternet */, isStrictMode);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400741 }
742
lucasline252a742019-03-12 13:08:03 +0800743 public void connectWithPartialConnectivity() {
744 setNetworkPartial();
745 connect(false);
746 }
747
lucaslin783f2212019-10-22 18:27:33 +0800748 public void connectWithPartialValidConnectivity(boolean isStrictMode) {
749 setNetworkPartialValid(isStrictMode);
750 connect(false, true /* hasInternet */, isStrictMode);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900751 }
752
lucaslin783f2212019-10-22 18:27:33 +0800753 void setNetworkValid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900754 mNmValidationResult = VALIDATION_RESULT_VALID;
755 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800756 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP;
757 if (isStrictMode) {
758 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
759 }
760 // The probesCompleted equals to probesSucceeded for the case of valid network, so put
761 // the same value into two different parameter of the method.
762 setProbesStatus(probesSucceeded, probesSucceeded);
Erik Kline1d3db322017-02-28 16:20:20 +0900763 }
764
lucaslin783f2212019-10-22 18:27:33 +0800765 void setNetworkInvalid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900766 mNmValidationResult = VALIDATION_RESULT_INVALID;
767 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800768 int probesCompleted = VALIDATION_RESULT_BASE;
769 int probesSucceeded = VALIDATION_RESULT_INVALID;
770 // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
771 // tried to validate the private DNS but failed.
772 if (isStrictMode) {
773 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
774 probesSucceeded = probesCompleted;
775 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
776 }
777 setProbesStatus(probesCompleted, probesSucceeded);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900778 }
779
lucaslin783f2212019-10-22 18:27:33 +0800780 void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
781 setNetworkInvalid(isStrictMode);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900782 mNmValidationRedirectUrl = redirectUrl;
lucaslin783f2212019-10-22 18:27:33 +0800783 // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
784 // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
785 int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
786 int probesSucceeded = VALIDATION_RESULT_INVALID;
787 if (isStrictMode) {
788 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
789 }
790 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400791 }
792
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900793 void setNetworkPartial() {
794 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
795 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800796 int probesCompleted = VALIDATION_RESULT_BASE;
797 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
798 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400799 }
Paul Jensene0988542015-06-25 15:30:08 -0400800
lucaslin783f2212019-10-22 18:27:33 +0800801 void setNetworkPartialValid(boolean isStrictMode) {
802 setNetworkPartial();
803 mNmValidationResult |= VALIDATION_RESULT_VALID;
804 int probesCompleted = VALIDATION_RESULT_BASE;
805 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
806 // Suppose the partial network cannot pass the private DNS validation as well, so only
807 // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
808 if (isStrictMode) {
809 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
810 }
811 setProbesStatus(probesCompleted, probesSucceeded);
812 }
813
814 void setProbesStatus(int probesCompleted, int probesSucceeded) {
815 mProbesCompleted = probesCompleted;
816 mProbesSucceeded = probesSucceeded;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900817 }
Paul Jensen232437312016-04-06 09:51:26 -0400818
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +0900819 void notifyCaptivePortalDataChanged(CaptivePortalData data) {
820 try {
821 mNmCallbacks.notifyCaptivePortalDataChanged(data);
822 } catch (RemoteException e) {
823 throw new AssertionError("This cannot happen", e);
824 }
825 }
826
Paul Jensen232437312016-04-06 09:51:26 -0400827 public String waitForRedirectUrl() {
828 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
829 return mRedirectUrl;
830 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900831
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900832 public void expectDisconnected() {
833 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900834 }
835
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900836 public void expectPreventReconnectReceived() {
837 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900838 }
Cody Kesting4f49f142020-01-06 16:55:35 -0800839
840 void notifyDataStallSuspected() throws Exception {
841 mNmCallbacks.notifyDataStallSuspected(
842 DATA_STALL_TIMESTAMP, DATA_STALL_DETECTION_METHOD, mDataStallExtras);
843 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400844 }
845
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900846 /**
847 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
848 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900849 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900850 * expectRemoveRequests.
851 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700852 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400853 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
854 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400855 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700856
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900857 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900858 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
859 // once, then cause some other thread to add or remove requests, then call
860 // waitForRequests().
861 // It is not possible to wait for both add and remove requests. When adding, the queue
862 // contains the expected score. When removing, the value is unused, all matters is the
863 // number of objects in the queue.
864 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900865
866 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900867 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900868 private boolean mExpectingAdditions;
869
Etan Cohenddb720a2019-01-08 12:09:18 -0800870 // Used to collect the networks requests managed by this factory. This is a duplicate of
871 // the internal information stored in the NetworkFactory (which is private).
872 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
873
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700874 public MockNetworkFactory(Looper looper, Context context, String logTag,
875 NetworkCapabilities filter) {
876 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900877 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700878 }
879
880 public int getMyRequestCount() {
881 return getRequestCount();
882 }
883
884 protected void startNetwork() {
885 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400886 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700887 }
888
889 protected void stopNetwork() {
890 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400891 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700892 }
893
894 public boolean getMyStartRequested() {
895 return mNetworkStarted.get();
896 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400897
898 public ConditionVariable getNetworkStartedCV() {
899 mNetworkStartedCV.close();
900 return mNetworkStartedCV;
901 }
902
903 public ConditionVariable getNetworkStoppedCV() {
904 mNetworkStoppedCV.close();
905 return mNetworkStoppedCV;
906 }
907
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900908 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900909 protected void handleAddRequest(NetworkRequest request, int score,
910 int factorySerialNumber) {
911 synchronized (mExpectations) {
912 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900913
Chalard Jean05ab6812018-05-02 21:14:54 +0900914 assertNotNull("Added more requests than expected (" + request + " score : "
915 + score + ")", expectedScore);
916 // If we're expecting anything, we must be expecting additions.
917 if (!mExpectingAdditions) {
918 fail("Can't add requests while expecting requests to be removed");
919 }
920 if (expectedScore != score) {
921 fail("Expected score was " + expectedScore + " but actual was " + score
922 + " in added request");
923 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900924
Chalard Jean05ab6812018-05-02 21:14:54 +0900925 // Add the request.
926 mNetworkRequests.put(request.requestId, request);
927 super.handleAddRequest(request, score, factorySerialNumber);
928 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900929 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400930 }
931
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900932 @Override
933 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900934 synchronized (mExpectations) {
935 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900936
Chalard Jean05ab6812018-05-02 21:14:54 +0900937 assertTrue("Removed more requests than expected", expectedScore != null);
938 // If we're expecting anything, we must be expecting removals.
939 if (mExpectingAdditions) {
940 fail("Can't remove requests while expecting requests to be added");
941 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900942
Chalard Jean05ab6812018-05-02 21:14:54 +0900943 // Remove the request.
944 mNetworkRequests.remove(request.requestId);
945 super.handleRemoveRequest(request);
946 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900947 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400948 }
949
Etan Cohenddb720a2019-01-08 12:09:18 -0800950 // Trigger releasing the request as unfulfillable
951 public void triggerUnfulfillable(NetworkRequest r) {
952 super.releaseRequestAsUnfulfillableByAnyFactory(r);
953 }
954
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900955 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900956 if (mExpectations.size() != 0) {
957 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900958 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400959 }
960
Chalard Jean05ab6812018-05-02 21:14:54 +0900961 // Expects that requests with the specified scores will be added.
962 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900963 assertNoExpectations();
964 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900965 for (int score : scores) {
966 mExpectations.add(score);
967 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400968 }
969
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900970 // Expects that count requests will be removed.
971 public void expectRemoveRequests(final int count) {
972 assertNoExpectations();
973 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900974 for (int i = 0; i < count; ++i) {
975 mExpectations.add(0); // For removals the score is ignored so any value will do.
976 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900977 }
978
979 // Waits for the expected request additions or removals to happen within a timeout.
980 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900981 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
982 synchronized (mExpectations) {
983 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
984 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
985 }
986 }
987 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900988 final String msg = count + " requests still not " +
989 (mExpectingAdditions ? "added" : "removed") +
990 " after " + TIMEOUT_MS + " ms";
991 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900992 }
993
Etan Cohenddb720a2019-01-08 12:09:18 -0800994 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
995 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900996 waitForRequests();
997 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800998 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400999 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07001000 }
1001
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001002 private static Looper startHandlerThreadAndReturnLooper() {
1003 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
1004 handlerThread.start();
1005 return handlerThread.getLooper();
1006 }
1007
1008 private class MockVpn extends Vpn {
1009 // TODO : the interactions between this mock and the mock network agent are too
1010 // hard to get right at this moment, because it's unclear in which case which
1011 // target needs to get a method call or both, and in what order. It's because
1012 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
1013 // parent class of MockVpn agent wants that responsibility.
1014 // That being said inside the test it should be possible to make the interactions
1015 // harder to get wrong with precise speccing, judicious comments, helper methods
1016 // and a few sprinkled assertions.
1017
1018 private boolean mConnected = false;
1019 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1020 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001021 private TestNetworkAgentWrapper mMockNetworkAgent;
Benedict Wong5d50ce82020-01-20 22:14:59 -08001022 private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001023
Cody Kestinga75e26b2020-01-05 14:06:39 -08001024 private VpnInfo mVpnInfo;
Cody Kesting3096b662020-03-18 21:11:29 +00001025 private Network[] mUnderlyingNetworks;
Cody Kestinga75e26b2020-01-05 14:06:39 -08001026
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001027 public MockVpn(int userId) {
1028 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
Benedict Wongb570e862020-01-17 19:33:55 -08001029 userId, mock(KeyStore.class));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001030 }
1031
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001032 public void setNetworkAgent(TestNetworkAgentWrapper agent) {
1033 agent.waitForIdle(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001034 mMockNetworkAgent = agent;
1035 mNetworkAgent = agent.getNetworkAgent();
1036 mNetworkCapabilities.set(agent.getNetworkCapabilities());
1037 }
1038
1039 public void setUids(Set<UidRange> uids) {
1040 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -08001041 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001042 }
1043
Benedict Wong5d50ce82020-01-20 22:14:59 -08001044 public void setVpnType(int vpnType) {
1045 mVpnType = vpnType;
1046 }
1047
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001048 @Override
1049 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -08001050 if (mMockNetworkAgent == null) {
1051 return NETID_UNSET;
1052 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001053 return mMockNetworkAgent.getNetwork().netId;
1054 }
1055
1056 @Override
1057 public boolean appliesToUid(int uid) {
1058 return mConnected; // Trickery to simplify testing.
1059 }
1060
1061 @Override
1062 protected boolean isCallerEstablishedOwnerLocked() {
1063 return mConnected; // Similar trickery
1064 }
1065
Benedict Wong5d50ce82020-01-20 22:14:59 -08001066 @Override
1067 public int getActiveAppVpnType() {
1068 return mVpnType;
1069 }
1070
Varun Anandc51b06d2019-02-25 17:22:02 -08001071 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001072 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1073 mConnected = true;
1074 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -08001075 mConfig.isMetered = isAlwaysMetered;
1076 }
1077
1078 public void connectAsAlwaysMetered() {
1079 connect(true /* isAlwaysMetered */);
1080 }
1081
1082 public void connect() {
1083 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001084 }
1085
1086 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001087 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1088 if (!mConnected) return null;
1089 super.updateCapabilities(defaultNetwork);
1090 // Because super.updateCapabilities will update the capabilities of the agent but
1091 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001092 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -08001093 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001094 }
1095
1096 private void copyCapabilitiesToNetworkAgent() {
1097 if (null != mMockNetworkAgent) {
1098 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1099 false /* sendToConnectivityService */);
1100 }
1101 }
1102
1103 public void disconnect() {
1104 mConnected = false;
1105 mConfig = null;
1106 }
Cody Kestinga75e26b2020-01-05 14:06:39 -08001107
1108 @Override
1109 public synchronized VpnInfo getVpnInfo() {
1110 if (mVpnInfo != null) return mVpnInfo;
1111
1112 return super.getVpnInfo();
1113 }
1114
Cody Kesting3096b662020-03-18 21:11:29 +00001115 private synchronized void setVpnInfo(VpnInfo vpnInfo) {
Cody Kestinga75e26b2020-01-05 14:06:39 -08001116 mVpnInfo = vpnInfo;
1117 }
Cody Kesting3096b662020-03-18 21:11:29 +00001118
1119 @Override
1120 public synchronized Network[] getUnderlyingNetworks() {
1121 if (mUnderlyingNetworks != null) return mUnderlyingNetworks;
1122
1123 return super.getUnderlyingNetworks();
1124 }
1125
1126 /** Don't override behavior for {@link Vpn#setUnderlyingNetworks}. */
1127 private synchronized void overrideUnderlyingNetworks(Network[] underlyingNetworks) {
1128 mUnderlyingNetworks = underlyingNetworks;
1129 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001130 }
1131
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001132 private void mockVpn(int uid) {
1133 synchronized (mService.mVpns) {
1134 int userId = UserHandle.getUserId(uid);
1135 mMockVpn = new MockVpn(userId);
1136 // This has no effect unless the VPN is actually connected, because things like
1137 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1138 // netId, and check if that network is actually connected.
1139 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001140 }
1141 }
1142
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001143 private void setUidRulesChanged(int uidRules) throws RemoteException {
1144 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1145 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001146
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001147 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
1148 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1149 }
1150
1151 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1152 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1153 }
1154
1155 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1156 volatile boolean mConfigRestrictsAvoidBadWifi;
1157 volatile int mConfigMeteredMultipathPreference;
1158
1159 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001160 super(c, h, r);
1161 }
1162
1163 @Override
1164 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001165 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +09001166 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001167
1168 @Override
1169 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001170 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +08001171 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001172 }
1173
Paul Jensen3d911462015-06-12 06:40:24 -04001174 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001175 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1176 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001177 */
1178 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001179 if (conditionVariable.block(TIMEOUT_MS)) {
1180 return;
1181 }
1182 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001183 }
1184
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001185 private static final int VPN_USER = 0;
1186 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1187 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1188 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1189
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001190 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001191 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001192 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001193
Hugo Benichi64901e52017-10-19 14:42:40 +09001194 MockitoAnnotations.initMocks(this);
1195 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1196
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001197 when(mUserManager.getUsers(eq(true))).thenReturn(
1198 Arrays.asList(new UserInfo[] {
1199 new UserInfo(VPN_USER, "", 0),
1200 }));
Qingxi Li9c5d8b92020-01-08 12:51:49 -08001201 final ApplicationInfo applicationInfo = new ApplicationInfo();
1202 applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1203 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
1204 .thenReturn(applicationInfo);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001205
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001206 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1207 // http://b/25897652 .
1208 if (Looper.myLooper() == null) {
1209 Looper.prepare();
1210 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001211 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001212
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001213 FakeSettingsProvider.clearSettingsProvider();
1214 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1215 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001216 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1217 LocalServices.addService(
1218 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001219
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001220 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1221 mAlarmManagerThread.start();
1222 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1223
1224 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1225 final ConnectivityService.Dependencies deps = makeDependencies();
1226 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001227 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001228 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001229 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001230 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001231 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001232 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001233 deps);
1234 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1235 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001236
Mike Yuf9729752018-08-17 15:22:05 +08001237 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1238 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1239 verify(mNpm).registerListener(policyListenerCaptor.capture());
1240 mPolicyListener = policyListenerCaptor.getValue();
1241
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001242 // Create local CM before sending system ready so that we can answer
1243 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001244 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001245 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001246 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001247 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001248
1249 // Ensure that the default setting for Captive Portals is used for most tests
1250 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001251 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001252 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001253 }
1254
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001255 private ConnectivityService.Dependencies makeDependencies() {
1256 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1257 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1258 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1259
1260 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1261 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1262 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
1263 doReturn(mNetworkStack).when(deps).getNetworkStack();
1264 doReturn(systemProperties).when(deps).getSystemProperties();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001265 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1266 doReturn(mMetricsService).when(deps).getMetricsLogger();
1267 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1268 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
Chalard Jean587758b2019-11-29 16:41:50 +09001269 doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001270 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1271 doAnswer(inv -> {
1272 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1273 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1274 return mPolicyTracker;
1275 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1276
1277 return deps;
1278 }
1279
1280 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1281 doAnswer(inv -> {
1282 final long when = inv.getArgument(1);
1283 final WakeupMessage wakeupMsg = inv.getArgument(3);
1284 final Handler handler = inv.getArgument(4);
1285
1286 long delayMs = when - SystemClock.elapsedRealtime();
1287 if (delayMs < 0) delayMs = 0;
1288 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1289 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1290 + "ms into the future: " + delayMs);
1291 }
1292 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1293 delayMs);
1294
1295 return null;
1296 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1297 any(WakeupMessage.class), any());
1298
1299 doAnswer(inv -> {
1300 final WakeupMessage wakeupMsg = inv.getArgument(0);
1301 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1302 return null;
1303 }).when(am).cancel(any(WakeupMessage.class));
1304 }
1305
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001306 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001307 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001308 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001309 if (mCellNetworkAgent != null) {
1310 mCellNetworkAgent.disconnect();
1311 mCellNetworkAgent = null;
1312 }
1313 if (mWiFiNetworkAgent != null) {
1314 mWiFiNetworkAgent.disconnect();
1315 mWiFiNetworkAgent = null;
1316 }
1317 if (mEthernetNetworkAgent != null) {
1318 mEthernetNetworkAgent.disconnect();
1319 mEthernetNetworkAgent = null;
1320 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001321 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001322
1323 mCsHandlerThread.quitSafely();
1324 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001325 }
1326
Rubin Xu9e64dc02019-04-23 18:04:14 +01001327 private void mockDefaultPackages() throws Exception {
1328 final String testPackageName = mContext.getPackageName();
1329 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1330 testPackageName, PackageManager.GET_PERMISSIONS);
1331 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1332 new String[] {testPackageName});
1333 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1334 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1335
1336 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1337 Arrays.asList(new PackageInfo[] {
1338 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1339 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1340 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1341 }));
1342 }
1343
Paul Jensend7b6ca92015-05-13 14:05:12 -04001344 private void verifyActiveNetwork(int transport) {
1345 // Test getActiveNetworkInfo()
1346 assertNotNull(mCm.getActiveNetworkInfo());
1347 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1348 // Test getActiveNetwork()
1349 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001350 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001351 if (!NetworkCapabilities.isValidTransport(transport)) {
1352 throw new IllegalStateException("Unknown transport " + transport);
1353 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001354 switch (transport) {
1355 case TRANSPORT_WIFI:
1356 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1357 break;
1358 case TRANSPORT_CELLULAR:
1359 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1360 break;
1361 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001362 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001363 }
1364 // Test getNetworkInfo(Network)
1365 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001366 assertEquals(transportToLegacyType(transport),
1367 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001368 // Test getNetworkCapabilities(Network)
1369 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1370 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1371 }
1372
1373 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001374 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001375 // Test getActiveNetworkInfo()
1376 assertNull(mCm.getActiveNetworkInfo());
1377 // Test getActiveNetwork()
1378 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001379 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001380 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001381 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001382 }
1383
1384 /**
1385 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1386 * broadcasts are received.
1387 */
Chalard Jean407deb72019-11-19 16:14:30 +09001388 private ConditionVariable registerConnectivityBroadcast(final int count) {
1389 return registerConnectivityBroadcastThat(count, intent -> true);
Chalard Jean9ca13772019-11-15 12:08:36 +09001390 }
1391
Chalard Jean407deb72019-11-19 16:14:30 +09001392 private ConditionVariable registerConnectivityBroadcastThat(final int count,
Chalard Jean9ca13772019-11-15 12:08:36 +09001393 @NonNull final Predicate<Intent> filter) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001394 final ConditionVariable cv = new ConditionVariable();
Chalard Jean9ca13772019-11-15 12:08:36 +09001395 final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
Chalard Jean9ca13772019-11-15 12:08:36 +09001396 final BroadcastReceiver receiver = new BroadcastReceiver() {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001397 private int remaining = count;
1398 public void onReceive(Context context, Intent intent) {
Chalard Jean9ca13772019-11-15 12:08:36 +09001399 if (!filter.test(intent)) return;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001400 if (--remaining == 0) {
1401 cv.open();
1402 mServiceContext.unregisterReceiver(this);
1403 }
1404 }
Chalard Jean9ca13772019-11-15 12:08:36 +09001405 };
1406 mServiceContext.registerReceiver(receiver, intentFilter);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001407 return cv;
1408 }
1409
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001410 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001411 public void testNetworkTypes() {
1412 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1413 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1414 // will fail. Failing here is much easier to debug.
1415 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1416 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001417 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1418 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1419
1420 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1421 // mocks, this assert exercises the ConnectivityService code path that ensures that
1422 // TYPE_ETHERNET is supported if the ethernet service is running.
1423 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001424 }
1425
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001426 @Test
Chalard Jean9ca13772019-11-15 12:08:36 +09001427 public void testNetworkFeature() throws Exception {
1428 // Connect the cell agent and wait for the connected broadcast.
1429 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1430 mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
Chalard Jean407deb72019-11-19 16:14:30 +09001431 final ConditionVariable cv1 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001432 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE);
1433 mCellNetworkAgent.connect(true);
1434 waitFor(cv1);
1435
1436 // Build legacy request for SUPL.
1437 final NetworkCapabilities legacyCaps = new NetworkCapabilities();
1438 legacyCaps.addTransportType(TRANSPORT_CELLULAR);
1439 legacyCaps.addCapability(NET_CAPABILITY_SUPL);
1440 final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
1441 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
1442
Automerger Merge Workerd40f64b2020-03-19 02:48:22 +00001443 // File request, withdraw it and make sure no broadcast is sent
1444 final ConditionVariable cv2 = registerConnectivityBroadcast(1);
Chalard Jean9ca13772019-11-15 12:08:36 +09001445 final TestNetworkCallback callback = new TestNetworkCallback();
Chalard Jean9ca13772019-11-15 12:08:36 +09001446 mCm.requestNetwork(legacyRequest, callback);
1447 callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
Automerger Merge Workerd40f64b2020-03-19 02:48:22 +00001448 mCm.unregisterNetworkCallback(callback);
1449 assertFalse(cv2.block(800)); // 800ms long enough to at least flake if this is sent
Chalard Jean9ca13772019-11-15 12:08:36 +09001450 // As the broadcast did not fire, the receiver was not unregistered. Do this now.
1451 mServiceContext.clearRegisteredReceivers();
1452
Automerger Merge Workerd40f64b2020-03-19 02:48:22 +00001453 // Disconnect the network and expect mobile disconnected broadcast. Use a small hack to
1454 // check that has been sent.
Chalard Jean9ca13772019-11-15 12:08:36 +09001455 final AtomicBoolean vanillaAction = new AtomicBoolean(false);
Automerger Merge Workerd40f64b2020-03-19 02:48:22 +00001456 final ConditionVariable cv3 = registerConnectivityBroadcastThat(1, intent -> {
Chalard Jean9ca13772019-11-15 12:08:36 +09001457 if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
1458 vanillaAction.set(true);
Chalard Jean9ca13772019-11-15 12:08:36 +09001459 }
1460 return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
1461 });
1462 mCellNetworkAgent.disconnect();
Automerger Merge Workerd40f64b2020-03-19 02:48:22 +00001463 waitFor(cv3);
Chalard Jean9ca13772019-11-15 12:08:36 +09001464 assertTrue(vanillaAction.get());
Chalard Jean9ca13772019-11-15 12:08:36 +09001465 }
1466
1467 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001468 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001469 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001470 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1471 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001472 assertNull(mCm.getActiveNetworkInfo());
1473 assertNull(mCm.getActiveNetwork());
1474 // Test bringing up validated cellular.
Chalard Jean407deb72019-11-19 16:14:30 +09001475 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001476 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001477 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001478 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001479 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001480 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1481 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1482 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1483 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1484 // Test bringing up validated WiFi.
Chalard Jean407deb72019-11-19 16:14:30 +09001485 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001486 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001487 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001488 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001489 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001490 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1491 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1492 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1493 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1494 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001495 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001496 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001497 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001498 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001499 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001500 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1501 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001502 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001503 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001504 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001505 verifyNoNetwork();
1506 }
1507
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001508 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001509 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1510 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001511 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001512 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001513 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001514 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001515 verifyActiveNetwork(TRANSPORT_WIFI);
1516 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001517 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001518 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001519 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001520 verifyActiveNetwork(TRANSPORT_WIFI);
1521 // Test cellular disconnect.
1522 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001523 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001524 verifyActiveNetwork(TRANSPORT_WIFI);
1525 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001526 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001527 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001528 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001529 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001530 verifyActiveNetwork(TRANSPORT_CELLULAR);
1531 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001532 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001533 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001534 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001535 verifyActiveNetwork(TRANSPORT_WIFI);
1536 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001537 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001538 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001539 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001540 verifyNoNetwork();
1541 }
1542
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001543 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001544 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1545 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001546 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001547 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001548 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001549 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001550 verifyActiveNetwork(TRANSPORT_CELLULAR);
1551 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001552 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001553 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001554 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001555 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001556 verifyActiveNetwork(TRANSPORT_WIFI);
1557 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001558 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001559 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001560 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001561 verifyActiveNetwork(TRANSPORT_CELLULAR);
1562 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001563 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001564 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001565 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001566 verifyNoNetwork();
1567 }
1568
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001569 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001570 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001571 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001572 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001573 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001574 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001575 waitFor(cv);
1576 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001577 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001578 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001579 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001580 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001581 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001582 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001583 waitFor(cv);
1584 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001585 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1586 NET_CAPABILITY_VALIDATED));
1587 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001588 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001589 mCellNetworkAgent.disconnect();
1590 waitFor(cv);
1591 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001592 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001593 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001594 NET_CAPABILITY_VALIDATED));
1595 }
1596
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001597 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001598 public void testCellularOutscoresWeakWifi() throws Exception {
1599 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001600 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001601 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001602 mCellNetworkAgent.connect(true);
1603 waitFor(cv);
1604 verifyActiveNetwork(TRANSPORT_CELLULAR);
1605 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001606 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001607 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001608 mWiFiNetworkAgent.connect(true);
1609 waitFor(cv);
1610 verifyActiveNetwork(TRANSPORT_WIFI);
1611 // Test WiFi getting really weak.
Chalard Jean407deb72019-11-19 16:14:30 +09001612 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001613 mWiFiNetworkAgent.adjustScore(-11);
1614 waitFor(cv);
1615 verifyActiveNetwork(TRANSPORT_CELLULAR);
1616 // Test WiFi restoring signal strength.
Chalard Jean407deb72019-11-19 16:14:30 +09001617 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001618 mWiFiNetworkAgent.adjustScore(11);
1619 waitFor(cv);
1620 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001621 }
1622
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001623 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001624 public void testReapingNetwork() throws Exception {
1625 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1626 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001627 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001628 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001629 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001630 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1631 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001632 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001633 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001634 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001635 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001636 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001637 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001638 mWiFiNetworkAgent.connect(true);
1639 waitFor(cv);
1640 verifyActiveNetwork(TRANSPORT_WIFI);
1641 // Test bringing up unvalidated cellular.
1642 // Expect it to be torn down because it could never be the highest scoring network
1643 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001644 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001645 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001646 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001647 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001648 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001649 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001650 }
1651
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001652 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001653 public void testCellularFallback() throws Exception {
1654 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001655 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001656 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001657 mCellNetworkAgent.connect(true);
1658 waitFor(cv);
1659 verifyActiveNetwork(TRANSPORT_CELLULAR);
1660 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001661 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001662 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001663 mWiFiNetworkAgent.connect(true);
1664 waitFor(cv);
1665 verifyActiveNetwork(TRANSPORT_WIFI);
1666 // Reevaluate WiFi (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001667 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001668 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1669 NET_CAPABILITY_VALIDATED));
1670 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1671 // Should quickly fall back to Cellular.
1672 waitFor(cv);
1673 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1674 NET_CAPABILITY_VALIDATED));
1675 verifyActiveNetwork(TRANSPORT_CELLULAR);
1676 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001677 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001678 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1679 NET_CAPABILITY_VALIDATED));
1680 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1681 // Should quickly fall back to WiFi.
1682 waitFor(cv);
1683 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1684 NET_CAPABILITY_VALIDATED));
1685 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1686 NET_CAPABILITY_VALIDATED));
1687 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001688 }
1689
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001690 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001691 public void testWiFiFallback() throws Exception {
1692 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001693 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001694 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001695 mWiFiNetworkAgent.connect(false);
1696 waitFor(cv);
1697 verifyActiveNetwork(TRANSPORT_WIFI);
1698 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001699 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001700 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001701 mCellNetworkAgent.connect(true);
1702 waitFor(cv);
1703 verifyActiveNetwork(TRANSPORT_CELLULAR);
1704 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001705 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001706 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1707 NET_CAPABILITY_VALIDATED));
1708 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1709 // Should quickly fall back to WiFi.
1710 waitFor(cv);
1711 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1712 NET_CAPABILITY_VALIDATED));
1713 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001714 }
1715
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001716 @Test
1717 public void testRequiresValidation() {
1718 assertTrue(NetworkMonitorUtils.isValidationRequired(
1719 mCm.getDefaultRequest().networkCapabilities));
1720 }
1721
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001722 /**
1723 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1724 * this class receives, by calling expectCallback() exactly once each time a callback is
1725 * received. assertNoCallback may be called at any time.
1726 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001727 private class TestNetworkCallback extends TestableNetworkCallback {
Chalard Jeanb299b842019-09-27 17:13:14 +09001728 TestNetworkCallback() {
1729 super(TEST_CALLBACK_TIMEOUT_MS);
1730 }
1731
Chalard Jean6f4216f2019-06-05 01:40:32 +09001732 @Override
1733 public void assertNoCallback() {
1734 // TODO: better support this use case in TestableNetworkCallback
1735 waitForIdle();
1736 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001737 }
Paul Jensen3d911462015-06-12 06:40:24 -04001738
Erik Klineacdd6392016-07-07 16:50:58 +09001739 @Override
Chalard Jean059c4262019-09-30 17:51:12 +09001740 public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
Chalard Jean6f4216f2019-06-05 01:40:32 +09001741 final long timeoutMs) {
1742 final T callback = super.expectCallback(type, n, timeoutMs);
Chalard Jean059c4262019-09-30 17:51:12 +09001743 if (callback instanceof CallbackEntry.Losing) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09001744 // TODO : move this to the specific test(s) needing this rather than here.
Chalard Jean059c4262019-09-30 17:51:12 +09001745 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001746 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001747 String msg = String.format(
1748 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001749 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001750 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001751 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001752 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001753 }
1754 }
1755
1756 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1757 // only be declared in a static or top level type".
1758 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1759 for (TestNetworkCallback c : callbacks) {
1760 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001761 }
1762 }
1763
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001764 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001765 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001766 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001767 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1768 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001769 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1770 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001771 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1772 .addTransportType(TRANSPORT_WIFI).build();
1773 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1774 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001775 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001776 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1777 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1778
1779 // Test unvalidated networks
Chalard Jean407deb72019-11-19 16:14:30 +09001780 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001781 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001782 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001783 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1784 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001785 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1786 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001787 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001788
Paul Jensen3d911462015-06-12 06:40:24 -04001789 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1790 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001791 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001792 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001793 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1794
Chalard Jean407deb72019-11-19 16:14:30 +09001795 cv = registerConnectivityBroadcast(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001796 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001797 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001798 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1799 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001800 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1801 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001802 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001803
Chalard Jean407deb72019-11-19 16:14:30 +09001804 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001805 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001806 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1807 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001808 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001809 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001810 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001811
Chalard Jean407deb72019-11-19 16:14:30 +09001812 cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001813 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001814 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1815 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001816 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001817 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001818
1819 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001820 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001821 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001822 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1823 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001824 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001825 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001826
Paul Jensen3d911462015-06-12 06:40:24 -04001827 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1828 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001829 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001830 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001831 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1832
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001833 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001834 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001835 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001836 genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001837 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001838 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001839 cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001840 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001841 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001842
Paul Jensen3d911462015-06-12 06:40:24 -04001843 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001844 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1845 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001846 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001847
Paul Jensen3d911462015-06-12 06:40:24 -04001848 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001849 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1850 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001851 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001852 }
1853
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001854 private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
1855 final TestNetworkCallback callback = new TestNetworkCallback();
1856 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
1857 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1858 .addTransportType(TRANSPORT_WIFI).build();
1859 mCm.registerNetworkCallback(wifiRequest, callback);
1860 mCm.registerDefaultNetworkCallback(defaultCallback);
1861
1862 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1863 mWiFiNetworkAgent.connect(false);
1864 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1865 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1866
1867 final LinkProperties newLp = new LinkProperties();
1868 final Uri capportUrl = Uri.parse("https://capport.example.com/api");
1869 final CaptivePortalData capportData = new CaptivePortalData.Builder()
1870 .setCaptive(true).build();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001871
1872 final Uri expectedCapportUrl = sanitized ? null : capportUrl;
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001873 newLp.setCaptivePortalApiUrl(capportUrl);
1874 mWiFiNetworkAgent.sendLinkProperties(newLp);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001875 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001876 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001877 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001878 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
1879
1880 final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
1881 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(capportData);
1882 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1883 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
1884 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1885 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001886
1887 final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
1888 assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
1889 assertEquals(expectedCapportData, lp.getCaptivePortalData());
1890 }
1891
1892 @Test
1893 public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
1894 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1895 PERMISSION_DENIED);
1896 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
1897 PERMISSION_DENIED);
1898 doNetworkCallbacksSanitizationTest(true /* sanitized */);
1899 }
1900
1901 @Test
1902 public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
1903 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1904 PERMISSION_GRANTED);
1905 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
1906 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1907 }
1908
1909 @Test
1910 public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
1911 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1912 PERMISSION_DENIED);
1913 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
1914 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1915 }
1916
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001917 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001918 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001919 // This test would be flaky with the default 120ms timer: that is short enough that
1920 // lingered networks are torn down before assertions can be run. We don't want to mock the
1921 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1922 // in detecting races.
1923 mService.mLingerDelayMs = 300;
1924
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001925 NetworkRequest request = new NetworkRequest.Builder()
1926 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1927 .build();
1928 TestNetworkCallback callback = new TestNetworkCallback();
1929 mCm.registerNetworkCallback(request, callback);
1930
1931 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1932 mCm.registerDefaultNetworkCallback(defaultCallback);
1933
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001934 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1935 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1936 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001937
1938 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1939 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1940 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1941
1942 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001943 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1944 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001945 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001946 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001947
1948 mWiFiNetworkAgent.connect(true);
1949 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1950 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001951 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001952 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001953 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001954 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001955 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001956 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001957 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001958
1959 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001960 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001961 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001962 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001963 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001964 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001965 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001966 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001967
1968 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001969 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
1970 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001971 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001972 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001973
1974 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001975 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001976 if (i % 2 == 0) {
1977 mWiFiNetworkAgent.adjustScore(-15);
1978 oldNetwork = mWiFiNetworkAgent;
1979 newNetwork = mCellNetworkAgent;
1980 } else {
1981 mWiFiNetworkAgent.adjustScore(15);
1982 oldNetwork = mCellNetworkAgent;
1983 newNetwork = mWiFiNetworkAgent;
1984
1985 }
Chalard Jean059c4262019-09-30 17:51:12 +09001986 callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001987 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1988 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001989 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001990 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1991 }
1992 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1993
1994 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1995 // if the network is still up.
1996 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001997 // We expect a notification about the capabilities change, and nothing else.
1998 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1999 defaultCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09002000 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002001 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002002
2003 // Wifi no longer satisfies our listen, which is for an unmetered network.
2004 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002005 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2006
2007 // Disconnect our test networks.
2008 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002009 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002010 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002011 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002012 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002013 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002014 waitForIdle();
2015 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002016
2017 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002018 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002019
2020 // Check that a network is only lingered or torn down if it would not satisfy a request even
2021 // if it validated.
2022 request = new NetworkRequest.Builder().clearCapabilities().build();
2023 callback = new TestNetworkCallback();
2024
2025 mCm.registerNetworkCallback(request, callback);
2026
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002027 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002028 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002029 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2030 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002031 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002032 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002033
2034 // Bring up wifi with a score of 20.
2035 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002036 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002037 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002038 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2039 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002040 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002041 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002042
2043 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002044 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2045 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002046 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002047 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002048 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002049
Chalard Jeanfb830762020-02-20 07:32:12 +00002050 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002051 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002052 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanfb830762020-02-20 07:32:12 +00002053 mWiFiNetworkAgent.adjustScore(50);
2054 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002055 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002056 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jeanfb830762020-02-20 07:32:12 +00002057 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002058 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002059 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002060
2061 // Tear down wifi.
2062 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002063 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2064 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002065 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002066 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002067 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002068
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002069 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2070 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002071 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002072 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002073 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002074 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002075 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002076 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002077 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002078 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002079 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002080
2081 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002082 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2083 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002084 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002085 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002086 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2087 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002088 waitForIdle();
2089 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002090
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002091 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002092 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002093 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002094 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2095 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002096 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002097 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002098 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002099 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2100 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002101 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002102 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002103 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002104 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002105
2106 NetworkRequest cellRequest = new NetworkRequest.Builder()
2107 .addTransportType(TRANSPORT_CELLULAR).build();
2108 NetworkCallback noopCallback = new NetworkCallback();
2109 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002110 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2111 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002112 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002113 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002114
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002115 // Similar to the above: lingering can start even after the lingered request is removed.
2116 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002117 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002118 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2119 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002120 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002121 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002122
2123 // Cell is now the default network. Pin it with a cell-specific request.
2124 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2125 mCm.requestNetwork(cellRequest, noopCallback);
2126
2127 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002128 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002129 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002130 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2131 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002132 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002133 // The default request is lingering on cell, but nothing happens to cell, and we send no
2134 // callbacks for it, because it's kept up by cellRequest.
2135 callback.assertNoCallback();
2136 // Now unregister cellRequest and expect cell to start lingering.
2137 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002138 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002139
2140 // Let linger run its course.
2141 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002142 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09002143 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002144
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002145 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2146 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2147 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002148 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002149 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002150 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002151 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002152 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002153 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002154 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2155 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002156 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002157
2158 // Let linger run its course.
Chalard Jean059c4262019-09-30 17:51:12 +09002159 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002160
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002161 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002162 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002163 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2164 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2165 trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002166
2167 mCm.unregisterNetworkCallback(callback);
2168 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002169 mCm.unregisterNetworkCallback(trackDefaultCallback);
2170 }
2171
paulhu86e23eb2019-11-05 18:05:05 +08002172 private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
2173 final String testPackageName = mContext.getPackageName();
2174 when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
2175 .thenReturn(buildPackageInfo(true, uid));
2176 mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
2177 }
2178
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002179 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002180 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002181 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08002182 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Chalard Jean1fa777d2018-02-16 16:07:53 +09002183 NetworkRequest request = new NetworkRequest.Builder()
2184 .clearCapabilities()
2185 .build();
2186 TestNetworkCallback callback = new TestNetworkCallback();
2187 mCm.registerNetworkCallback(request, callback);
2188
2189 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2190 mCm.registerDefaultNetworkCallback(defaultCallback);
2191
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002192 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2193 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002194
2195 mCellNetworkAgent.connect(true);
2196 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2197 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2198
2199 // Wifi comes up and cell lingers.
2200 mWiFiNetworkAgent.connect(true);
2201 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2202 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002203 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002204 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2205
2206 // File a request for cellular, then release it.
2207 NetworkRequest cellRequest = new NetworkRequest.Builder()
2208 .addTransportType(TRANSPORT_CELLULAR).build();
2209 NetworkCallback noopCallback = new NetworkCallback();
2210 mCm.requestNetwork(cellRequest, noopCallback);
2211 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002212 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002213
2214 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002215 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002216 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2217 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2218 lingerTimeoutMs);
2219
2220 // Clean up.
2221 mCm.unregisterNetworkCallback(defaultCallback);
2222 mCm.unregisterNetworkCallback(callback);
2223 }
2224
2225 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002226 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002227 NetworkRequest request = new NetworkRequest.Builder()
2228 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2229 .build();
2230 TestNetworkCallback callback = new TestNetworkCallback();
2231 mCm.registerNetworkCallback(request, callback);
2232
2233 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002234 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002235 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002236 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002237
2238 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002239 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002240 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002241 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002242 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002243
2244 // Cell Remains the default.
2245 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2246
2247 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2248 // it's explicitly selected.
2249 mWiFiNetworkAgent.adjustScore(-40);
2250 mWiFiNetworkAgent.adjustScore(40);
2251 callback.assertNoCallback();
2252
2253 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2254 // wifi even though it's unvalidated.
2255 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002256 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002257 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2258
2259 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2260 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002261 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002262 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002263 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002264 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002265 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002266
2267 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2268 // network to disconnect.
2269 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002270 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002271
2272 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002273 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002274 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002275 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002276 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002277 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002278 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2279 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2280
2281 // BUG: the network will no longer linger, even though it's validated and outscored.
2282 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002283 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002284 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002285 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002286 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2287 callback.assertNoCallback();
2288
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002289 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
2290 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
2291 // wifi immediately.
2292 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002293 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002294 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002295 mWiFiNetworkAgent.explicitlySelected(true, true);
2296 mWiFiNetworkAgent.connect(false);
2297 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002298 callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002299 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2300 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002301 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002302
2303 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
2304 // Check that the network is not scored specially and that the device prefers cell data.
2305 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002306 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002307 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002308 mWiFiNetworkAgent.explicitlySelected(false, true);
2309 mWiFiNetworkAgent.connect(false);
2310 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2311 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2312
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002313 // Clean up.
2314 mWiFiNetworkAgent.disconnect();
2315 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002316
Chalard Jean059c4262019-09-30 17:51:12 +09002317 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2318 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002319 }
2320
Chalard Jean05ab6812018-05-02 21:14:54 +09002321 private int[] makeIntArray(final int size, final int value) {
2322 final int[] array = new int[size];
2323 Arrays.fill(array, value);
2324 return array;
2325 }
2326
Paul Jensen85cf78e2015-06-25 13:25:07 -04002327 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002328 // Verify NOT_RESTRICTED is set appropriately
2329 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2330 .build().networkCapabilities;
2331 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2332 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2333 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002334 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002335 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2336 } else {
2337 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2338 }
2339
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002340 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002341 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002342 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2343 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002344 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002345 mServiceContext, "testFactory", filter);
2346 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002347 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002348 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002349 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002350 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002351 int expectedRequestCount = 1;
2352 NetworkCallback networkCallback = null;
2353 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2354 // add one.
2355 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002356 assertFalse(testFactory.getMyStartRequested());
2357 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2358 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002359 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002360 mCm.requestNetwork(request, networkCallback);
2361 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002362 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002363 }
Paul Jensen3d911462015-06-12 06:40:24 -04002364 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002365 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2366 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002367
Paul Jensen85cf78e2015-06-25 13:25:07 -04002368 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002369 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002370 // Rather than create a validated network which complicates things by registering it's
2371 // own NetworkRequest during startup, just bump up the score to cancel out the
2372 // unvalidated penalty.
2373 testAgent.adjustScore(40);
2374 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002375
2376 // When testAgent connects, ConnectivityService will re-send us all current requests with
2377 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2378 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002379 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002380 testAgent.connect(false);
2381 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002382 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002383 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002384 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002385
Paul Jensen85cf78e2015-06-25 13:25:07 -04002386 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002387 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002388 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002389 ConnectivityManager.NetworkCallback[] networkCallbacks =
2390 new ConnectivityManager.NetworkCallback[10];
2391 for (int i = 0; i< networkCallbacks.length; i++) {
2392 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2393 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002394 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002395 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2396 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002397 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2398 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002399
Paul Jensen85cf78e2015-06-25 13:25:07 -04002400 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002401 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002402 for (int i = 0; i < networkCallbacks.length; i++) {
2403 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2404 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002405 testFactory.waitForNetworkRequests(expectedRequestCount);
2406 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002407
Paul Jensen85cf78e2015-06-25 13:25:07 -04002408 // Drop the higher scored network.
2409 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002410 // With the default network disconnecting, the requests are sent with score 0 to factories.
2411 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002412 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002413 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002414 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002415 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2416 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002417
Lorenzo Colittif1080a92020-03-02 19:46:35 +09002418 testFactory.terminate();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002419 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002420 handlerThread.quit();
2421 }
2422
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002423 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002424 public void testNetworkFactoryRequests() throws Exception {
2425 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2426 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2427 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2428 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2429 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2430 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2431 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2432 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2433 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2434 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2435 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2436 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2437 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2438 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2439 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2440 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2441 }
2442
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002443 @Test
Lorenzo Colittif1080a92020-03-02 19:46:35 +09002444 public void testNetworkFactoryUnregister() throws Exception {
2445 final NetworkCapabilities filter = new NetworkCapabilities();
2446 filter.clearAll();
2447
2448 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2449 handlerThread.start();
2450
2451 // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it
2452 // does not crash.
2453 for (int i = 0; i < 100; i++) {
2454 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
2455 mServiceContext, "testFactory", filter);
2456 // Register the factory and don't be surprised when the default request arrives.
Lorenzo Colittif1080a92020-03-02 19:46:35 +09002457 testFactory.expectAddRequestsWithScores(0);
Junyu Lai2762be92020-03-18 10:01:45 +00002458 testFactory.register();
Lorenzo Colittif1080a92020-03-02 19:46:35 +09002459 testFactory.waitForNetworkRequests(1);
2460
2461 testFactory.setScoreFilter(42);
2462 testFactory.terminate();
2463
2464 if (i % 2 == 0) {
2465 try {
2466 testFactory.register();
2467 fail("Re-registering terminated NetworkFactory should throw");
2468 } catch (IllegalStateException expected) {
2469 }
2470 }
2471 }
2472 handlerThread.quit();
2473 }
2474
2475 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002476 public void testNoMutableNetworkRequests() throws Exception {
2477 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002478 NetworkRequest request1 = new NetworkRequest.Builder()
2479 .addCapability(NET_CAPABILITY_VALIDATED)
2480 .build();
2481 NetworkRequest request2 = new NetworkRequest.Builder()
2482 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2483 .build();
2484
2485 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002486 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2487 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2488 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2489 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002490 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002491
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002492 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002493 public void testMMSonWiFi() throws Exception {
2494 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002495 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002496 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002497 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002498 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002499 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002500 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002501 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002502
Paul Jensene0988542015-06-25 15:30:08 -04002503 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002504 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09002505 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002506 mWiFiNetworkAgent.connect(true);
2507 waitFor(cv);
2508 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002509
Paul Jensene0988542015-06-25 15:30:08 -04002510 // Register MMS NetworkRequest
2511 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2512 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2513 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2514 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002515
Paul Jensene0988542015-06-25 15:30:08 -04002516 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002517 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002518 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002519 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002520 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002521 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002522
Paul Jensene0988542015-06-25 15:30:08 -04002523 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002524 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002525 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002526 verifyActiveNetwork(TRANSPORT_WIFI);
2527 }
2528
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002529 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002530 public void testMMSonCell() throws Exception {
2531 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002532 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09002533 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002534 mCellNetworkAgent.connect(false);
2535 waitFor(cv);
2536 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002537
Paul Jensene0988542015-06-25 15:30:08 -04002538 // Register MMS NetworkRequest
2539 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2540 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2541 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2542 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002543
Paul Jensene0988542015-06-25 15:30:08 -04002544 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002545 TestNetworkAgentWrapper
2546 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002547 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2548 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002549 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002550 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002551
Paul Jensene0988542015-06-25 15:30:08 -04002552 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002553 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002554 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002555 verifyActiveNetwork(TRANSPORT_CELLULAR);
2556 }
2557
lucaslinf3b59b32019-03-26 17:49:49 +08002558 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002559 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002560 // Register network callback.
2561 NetworkRequest request = new NetworkRequest.Builder()
2562 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2563 .build();
2564 TestNetworkCallback callback = new TestNetworkCallback();
2565 mCm.registerNetworkCallback(request, callback);
2566
2567 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002568 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002569 mCellNetworkAgent.connect(true);
2570 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2571
2572 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002573 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002574 mWiFiNetworkAgent.connectWithPartialConnectivity();
2575 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2576 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2577
2578 // Mobile data should be the default network.
2579 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2580 callback.assertNoCallback();
2581
lucaslinf3b59b32019-03-26 17:49:49 +08002582 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2583 // probe.
lucaslin783f2212019-10-22 18:27:33 +08002584 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
lucasline252a742019-03-12 13:08:03 +08002585 // If the user chooses yes to use this partial connectivity wifi, switch the default
2586 // network to wifi and check if wifi becomes valid or not.
2587 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2588 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002589 // If user accepts partial connectivity network,
2590 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002591 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002592 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002593
lucaslinf3b59b32019-03-26 17:49:49 +08002594 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2595 // validated.
2596 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002597 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002598 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2599 mWiFiNetworkAgent);
2600 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2601 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2602
2603 // Disconnect and reconnect wifi with partial connectivity again.
2604 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002605 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002606 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002607 mWiFiNetworkAgent.connectWithPartialConnectivity();
2608 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2609 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2610
2611 // Mobile data should be the default network.
2612 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2613
2614 // If the user chooses no, disconnect wifi immediately.
2615 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2616 false /* always */);
Chalard Jean059c4262019-09-30 17:51:12 +09002617 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002618
2619 // If user accepted partial connectivity before, and device reconnects to that network
2620 // again, but now the network has full connectivity. The network shouldn't contain
2621 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002622 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002623 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002624 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2625 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002626 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002627
lucaslinf3b59b32019-03-26 17:49:49 +08002628 // If user accepted partial connectivity network before,
2629 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2630 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002631 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002632 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002633 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002634 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2635 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002636
lucasline252a742019-03-12 13:08:03 +08002637 // Wifi should be the default network.
2638 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2639 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002640 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002641
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002642 // The user accepted partial connectivity and selected "don't ask again". Now the user
2643 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2644 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002645 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002646 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2647 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002648 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002649 // If user accepted partial connectivity network before,
2650 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2651 // ConnectivityService#updateNetworkInfo().
lucaslinf3b59b32019-03-26 17:49:49 +08002652 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002653 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002654 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002655 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002656 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
lucaslin783f2212019-10-22 18:27:33 +08002657 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002658
lucaslinf3b59b32019-03-26 17:49:49 +08002659 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2660 // validated.
2661 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2662 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2663 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002664 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002665
2666 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2667 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002668 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002669 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2670 true /* acceptUnvalidated */);
2671
2672 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2673 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2674 // notifyNetworkConnected.
lucaslin783f2212019-10-22 18:27:33 +08002675 mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002676 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002677 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002678 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002679 callback.expectCapabilitiesWith(
2680 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2681 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002682 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002683 }
2684
2685 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002686 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002687 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2688 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2689 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2690 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2691
2692 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2693 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2694 .addCapability(NET_CAPABILITY_VALIDATED).build();
2695 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2696
2697 // Bring up a network with a captive portal.
2698 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002699 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002700 String redirectUrl = "http://android.com/path";
lucaslin783f2212019-10-22 18:27:33 +08002701 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002702 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002703 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002704
2705 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2706 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2707 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2708 .launchCaptivePortalApp();
2709
2710 // Report that the captive portal is dismissed with partial connectivity, and check that
2711 // callbacks are fired.
2712 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002713 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002714 waitForIdle();
2715 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2716 mWiFiNetworkAgent);
2717
2718 // Report partial connectivity is accepted.
lucaslin783f2212019-10-22 18:27:33 +08002719 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002720 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2721 false /* always */);
2722 waitForIdle();
2723 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002724 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002725 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2726 NetworkCapabilities nc =
2727 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2728 mWiFiNetworkAgent);
2729
2730 mCm.unregisterNetworkCallback(captivePortalCallback);
2731 mCm.unregisterNetworkCallback(validatedCallback);
2732 }
2733
2734 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002735 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002736 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2737 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2738 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2739 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2740
2741 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2742 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2743 .addCapability(NET_CAPABILITY_VALIDATED).build();
2744 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002745
2746 // Bring up a network with a captive portal.
2747 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002748 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002749 String firstRedirectUrl = "http://example.com/firstPath";
lucaslin783f2212019-10-22 18:27:33 +08002750 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002751 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002752 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002753
2754 // Take down network.
2755 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002756 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002757 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002758
2759 // Bring up a network with a captive portal.
2760 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002761 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002762 String secondRedirectUrl = "http://example.com/secondPath";
lucaslin783f2212019-10-22 18:27:33 +08002763 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002764 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002765 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002766
2767 // Make captive portal disappear then revalidate.
2768 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
lucaslin783f2212019-10-22 18:27:33 +08002769 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002770 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002771 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002772
2773 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002774 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002775
2776 // Break network connectivity.
2777 // Expect NET_CAPABILITY_VALIDATED onLost callback.
lucaslin783f2212019-10-22 18:27:33 +08002778 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002779 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean059c4262019-09-30 17:51:12 +09002780 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002781 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002782
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002783 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002784 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002785 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2786 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2787 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2788 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2789
2790 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2791 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2792 .addCapability(NET_CAPABILITY_VALIDATED).build();
2793 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2794
2795 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002796 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002797 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002798 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002799 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2800
2801 // Check that calling startCaptivePortalApp does nothing.
2802 final int fastTimeoutMs = 100;
2803 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002804 waitForIdle();
2805 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002806 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2807
2808 // Turn into a captive portal.
lucaslin783f2212019-10-22 18:27:33 +08002809 mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002810 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002811 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002812 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002813
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002814 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002815 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002816 waitForIdle();
2817 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2818
2819 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2820 final Bundle testBundle = new Bundle();
2821 final String testKey = "testkey";
2822 final String testValue = "testvalue";
2823 testBundle.putString(testKey, testValue);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09002824 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2825 PERMISSION_GRANTED);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002826 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2827 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2828 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2829 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002830
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002831 // Report that the captive portal is dismissed, and check that callbacks are fired
lucaslin783f2212019-10-22 18:27:33 +08002832 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002833 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002834 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002835 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002836
2837 mCm.unregisterNetworkCallback(validatedCallback);
2838 mCm.unregisterNetworkCallback(captivePortalCallback);
2839 }
2840
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002841 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002842 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002843 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2844 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2845 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2846 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2847
2848 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2849 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2850 .addCapability(NET_CAPABILITY_VALIDATED).build();
2851 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2852
2853 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2854 // Bring up a network with a captive portal.
2855 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002856 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002857 String firstRedirectUrl = "http://example.com/firstPath";
2858
lucaslin783f2212019-10-22 18:27:33 +08002859 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002860 mWiFiNetworkAgent.expectDisconnected();
2861 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002862
2863 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002864 }
2865
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09002866 @Test
2867 public void testCaptivePortalApi() throws Exception {
2868 mServiceContext.setPermission(
2869 android.Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
2870
2871 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2872 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2873 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2874 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2875
2876 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2877 final String redirectUrl = "http://example.com/firstPath";
2878
2879 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
2880 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2881
2882 final CaptivePortalData testData = new CaptivePortalData.Builder()
2883 .setUserPortalUrl(Uri.parse(redirectUrl))
2884 .setBytesRemaining(12345L)
2885 .build();
2886
2887 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(testData);
2888
2889 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
2890 lp -> testData.equals(lp.getCaptivePortalData()));
2891
2892 final LinkProperties newLps = new LinkProperties();
2893 newLps.setMtu(1234);
2894 mWiFiNetworkAgent.sendLinkProperties(newLps);
2895 // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
2896 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
2897 lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
2898 }
2899
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002900 private NetworkRequest.Builder newWifiRequestBuilder() {
2901 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2902 }
2903
Etan Cohen836ad572018-12-30 17:59:59 -08002904 /**
2905 * Verify request matching behavior with network specifiers.
2906 *
2907 * Note: this test is somewhat problematic since it involves removing capabilities from
2908 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2909 * as a WTF bug in
2910 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2911 * does work.
2912 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002913 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002914 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002915 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2916 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2917 Parcelable {
2918 @Override
Chalard Jean2da4f9f2020-03-27 17:57:34 +09002919 public boolean canBeSatisfiedBy(NetworkSpecifier other) {
Etan Cohen836ad572018-12-30 17:59:59 -08002920 return true;
2921 }
2922
2923 @Override
2924 public int describeContents() {
2925 return 0;
2926 }
2927
2928 @Override
2929 public void writeToParcel(Parcel dest, int flags) {}
2930
2931 @Override
2932 public NetworkSpecifier redact() {
2933 return null;
2934 }
2935 }
2936
2937 // A network specifier that matches either another LocalNetworkSpecifier with the same
2938 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2939 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2940 private String mString;
2941
2942 LocalStringNetworkSpecifier(String string) {
2943 mString = string;
2944 }
2945
2946 @Override
Chalard Jean2da4f9f2020-03-27 17:57:34 +09002947 public boolean canBeSatisfiedBy(NetworkSpecifier other) {
Etan Cohen836ad572018-12-30 17:59:59 -08002948 if (other instanceof LocalStringNetworkSpecifier) {
2949 return TextUtils.equals(mString,
2950 ((LocalStringNetworkSpecifier) other).mString);
2951 }
2952 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2953 return false;
2954 }
2955
2956 @Override
2957 public int describeContents() {
2958 return 0;
2959 }
2960 @Override
2961 public void writeToParcel(Parcel dest, int flags) {}
2962 }
2963
2964
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002965 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002966 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002967 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002968 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2969 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002970 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2971 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002972 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002973 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002974
2975 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2976 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2977 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002978 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002979 TestNetworkCallback cFoo = new TestNetworkCallback();
2980 TestNetworkCallback cBar = new TestNetworkCallback();
2981 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002982 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002983
2984 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2985 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2986 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002987 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002988 mCm.registerNetworkCallback(rFoo, cFoo);
2989 mCm.registerNetworkCallback(rBar, cBar);
2990
Etan Cohen836ad572018-12-30 17:59:59 -08002991 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2992 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2993
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002994 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002995 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002996 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2997 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2998 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2999 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003000 assertNoCallbacks(cFoo, cBar);
3001
Etan Cohen836ad572018-12-30 17:59:59 -08003002 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003003 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003004 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003005 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3006 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003007 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003008 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
3009 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08003010 assertEquals(nsFoo,
3011 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003012 cFoo.assertNoCallback();
3013
Etan Cohen836ad572018-12-30 17:59:59 -08003014 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean059c4262019-09-30 17:51:12 +09003015 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003016 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003017 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003018 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3019 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003020 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003021 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
3022 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08003023 assertEquals(nsBar,
3024 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3025 cBar.assertNoCallback();
3026
3027 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
3028 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3029 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003030 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3031 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08003032 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003033 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
3034 (caps) -> caps.getNetworkSpecifier() == null);
3035 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
3036 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08003037 assertNull(
3038 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3039 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003040 cBar.assertNoCallback();
3041
3042 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean059c4262019-09-30 17:51:12 +09003043 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3044 cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003045 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean059c4262019-09-30 17:51:12 +09003046 c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003047 }
3048
Etan Cohen836ad572018-12-30 17:59:59 -08003049 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003050 }
3051
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003052 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08003053 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09003054 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003055 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07003056 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003057 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003058
Chalard Jean751bb3f2019-06-19 23:29:58 +09003059 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003060 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3061 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07003062 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08003063 mService.requestNetwork(networkCapabilities, null, 0, null,
Qingxi Li9c5d8b92020-01-08 12:51:49 -08003064 ConnectivityManager.TYPE_WIFI, mContext.getPackageName());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003065 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003066
Etan Cohena7434272017-04-03 12:17:51 -07003067 class NonParcelableSpecifier extends NetworkSpecifier {
Chalard Jean2da4f9f2020-03-27 17:57:34 +09003068 @Override
3069 public boolean canBeSatisfiedBy(NetworkSpecifier other) {
3070 return false;
3071 }
Etan Cohena7434272017-04-03 12:17:51 -07003072 };
3073 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3074 @Override public int describeContents() { return 0; }
3075 @Override public void writeToParcel(Parcel p, int flags) {}
3076 }
Etan Cohena7434272017-04-03 12:17:51 -07003077
Chalard Jean751bb3f2019-06-19 23:29:58 +09003078 final NetworkRequest.Builder builder =
3079 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3080 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07003081 builder.setNetworkSpecifier(new NonParcelableSpecifier());
3082 Parcel parcelW = Parcel.obtain();
3083 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003084 });
Etan Cohena7434272017-04-03 12:17:51 -07003085
Chalard Jean751bb3f2019-06-19 23:29:58 +09003086 final NetworkRequest nr =
3087 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
3088 .setNetworkSpecifier(new ParcelableSpecifier())
3089 .build();
Etan Cohena7434272017-04-03 12:17:51 -07003090 assertNotNull(nr);
3091
Chalard Jean751bb3f2019-06-19 23:29:58 +09003092 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07003093 Parcel parcelW = Parcel.obtain();
3094 nr.writeToParcel(parcelW, 0);
3095 byte[] bytes = parcelW.marshall();
3096 parcelW.recycle();
3097
3098 Parcel parcelR = Parcel.obtain();
3099 parcelR.unmarshall(bytes, 0, bytes.length);
3100 parcelR.setDataPosition(0);
3101 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003102 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003103 }
3104
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003105 @Test
Roshan Piuse38acab2020-01-16 12:17:17 -08003106 public void testNetworkRequestUidSpoofSecurityException() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003107 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07003108 mWiFiNetworkAgent.connect(false);
Roshan Piuse38acab2020-01-16 12:17:17 -08003109 NetworkRequest networkRequest = newWifiRequestBuilder().build();
Etan Cohen859748f2017-04-03 17:42:34 -07003110 TestNetworkCallback networkCallback = new TestNetworkCallback();
Roshan Piuse38acab2020-01-16 12:17:17 -08003111 doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003112 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07003113 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003114 });
Etan Cohen859748f2017-04-03 17:42:34 -07003115 }
3116
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003117 @Test
paulhu3d67f532019-03-22 16:35:06 +08003118 public void testInvalidSignalStrength() {
3119 NetworkRequest r = new NetworkRequest.Builder()
3120 .addCapability(NET_CAPABILITY_INTERNET)
3121 .addTransportType(TRANSPORT_WIFI)
3122 .setSignalStrength(-75)
3123 .build();
3124 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3125 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003126 assertThrows(SecurityException.class, () ->
3127 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003128
Chalard Jean751bb3f2019-06-19 23:29:58 +09003129 assertThrows(SecurityException.class, () ->
3130 mCm.registerNetworkCallback(r, PendingIntent.getService(
3131 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003132
3133 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003134 assertThrows(IllegalArgumentException.class, () ->
3135 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003136
Chalard Jean751bb3f2019-06-19 23:29:58 +09003137 assertThrows(IllegalArgumentException.class, () ->
3138 mCm.requestNetwork(r, PendingIntent.getService(
3139 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003140 }
3141
3142 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003143 public void testRegisterDefaultNetworkCallback() throws Exception {
3144 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3145 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3146 defaultNetworkCallback.assertNoCallback();
3147
3148 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3149 // whenever Wi-Fi is up. Without this, the mobile network agent is
3150 // reaped before any other activity can take place.
3151 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3152 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3153 .addTransportType(TRANSPORT_CELLULAR).build();
3154 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3155 cellNetworkCallback.assertNoCallback();
3156
3157 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003158 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003159 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003160 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3161 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003162 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003163
3164 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003165 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09003166 mWiFiNetworkAgent.connect(true);
3167 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003168 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003169 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003170
3171 // Bring down cell. Expect no default network callback, since it wasn't the default.
3172 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003173 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003174 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003175 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003176
3177 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003178 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003179 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003180 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003181 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003182 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003183
3184 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3185 // followed by AVAILABLE cell.
3186 mWiFiNetworkAgent.disconnect();
3187 cellNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09003188 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003189 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003190 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003191 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3192 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003193 waitForIdle();
3194 assertEquals(null, mCm.getActiveNetwork());
3195
3196 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003197 final TestNetworkAgentWrapper
3198 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003199 final ArraySet<UidRange> ranges = new ArraySet<>();
3200 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003201 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3202 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003203 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003204 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003205 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3206 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3207
3208 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003209 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003210 waitForIdle();
3211 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003212 }
3213
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003214 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003215 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003216 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003217 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003218 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3219 .addTransportType(TRANSPORT_CELLULAR).build();
3220 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3221
3222 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003223 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09003224 mCellNetworkAgent.connect(true);
3225
Erik Kline1d3db322017-02-28 16:20:20 +09003226 // We should get onAvailable(), onCapabilitiesChanged(), and
3227 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3228 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003229 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003230 cellNetworkCallback.assertNoCallback();
3231
3232 // Update LinkProperties.
3233 final LinkProperties lp = new LinkProperties();
3234 lp.setInterfaceName("foonet_data0");
3235 mCellNetworkAgent.sendLinkProperties(lp);
3236 // We should get onLinkPropertiesChanged().
Chalard Jean059c4262019-09-30 17:51:12 +09003237 cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Chalard Jean6f4216f2019-06-05 01:40:32 +09003238 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003239 cellNetworkCallback.assertNoCallback();
3240
Erik Kline1d3db322017-02-28 16:20:20 +09003241 // Suspend the network.
3242 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003243 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3244 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003245 cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003246 cellNetworkCallback.assertNoCallback();
Chiachang Wanga5d8fe82020-02-12 17:01:59 +08003247 assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
Erik Kline1d3db322017-02-28 16:20:20 +09003248
Erik Klineacdd6392016-07-07 16:50:58 +09003249 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003250 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003251 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003252 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3253 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003254 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003255 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003256 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3257
3258 mCellNetworkAgent.resume();
3259 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3260 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003261 cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09003262 cellNetworkCallback.assertNoCallback();
Chiachang Wanga5d8fe82020-02-12 17:01:59 +08003263 assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
Chalard Jean804b8fb2018-01-30 22:41:41 +09003264
3265 dfltNetworkCallback = new TestNetworkCallback();
3266 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3267 // This time onNetworkSuspended should not be called.
3268 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3269 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003270
Erik Klineacdd6392016-07-07 16:50:58 +09003271 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3272 mCm.unregisterNetworkCallback(cellNetworkCallback);
3273 }
3274
Calvin On1f64f3f2016-10-11 15:10:46 -07003275 private void setCaptivePortalMode(int mode) {
3276 ContentResolver cr = mServiceContext.getContentResolver();
3277 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3278 }
3279
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003280 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003281 ContentResolver cr = mServiceContext.getContentResolver();
3282 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003283 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003284 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003285 }
3286
Erik Kline79c6d052018-03-21 07:18:33 -07003287 private void setPrivateDnsSettings(String mode, String specifier) {
3288 final ContentResolver cr = mServiceContext.getContentResolver();
3289 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3290 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3291 mService.updatePrivateDnsSettings();
3292 waitForIdle();
3293 }
3294
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003295 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003296 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3297 assertNotNull(nc);
3298 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3299 }
3300
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003301 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003302 public void testBackgroundNetworks() throws Exception {
3303 // Create a background request. We can't do this ourselves because ConnectivityService
3304 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003305 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08003306 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003307 final NetworkRequest request = new NetworkRequest.Builder().build();
3308 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3309 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3310 final TestNetworkCallback callback = new TestNetworkCallback();
3311 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3312 mCm.registerNetworkCallback(request, callback);
3313 mCm.registerNetworkCallback(fgRequest, fgCallback);
3314
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003315 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003316 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003317 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3318 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003319 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3320
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003321 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003322 mWiFiNetworkAgent.connect(true);
3323
3324 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003325 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003326 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003327 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003328 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003329 fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003330 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003331 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3332 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3333
3334 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003335 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003336 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09003337 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003338 // Expect a network capabilities update sans FOREGROUND.
3339 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003340 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3341 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3342
3343 // File a cell request and check that cell comes into the foreground.
3344 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3345 .addTransportType(TRANSPORT_CELLULAR).build();
3346 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3347 mCm.requestNetwork(cellRequest, cellCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003348 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3349 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003350 // Expect a network capabilities update with FOREGROUND, because the most recent
3351 // request causes its state to change.
Chalard Jean28e6b262019-11-19 21:30:44 +09003352 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003353 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003354 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3355 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3356
3357 // Release the request. The network immediately goes into the background, since it was not
3358 // lingering.
3359 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09003360 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003361 // Expect a network capabilities update sans FOREGROUND.
3362 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003363 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3364 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3365
3366 // Disconnect wifi and check that cell is foreground again.
3367 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003368 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3369 fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003370 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003371 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3372
3373 mCm.unregisterNetworkCallback(callback);
3374 mCm.unregisterNetworkCallback(fgCallback);
3375 }
3376
Hugo Benichi849b81b2017-05-25 13:42:31 +09003377 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003378 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003379 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003380 // Benchmarks connecting and switching performance in the presence of a large number of
3381 // NetworkRequests.
3382 // 1. File NUM_REQUESTS requests.
3383 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3384 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3385 // and NUM_REQUESTS onAvailable callbacks to fire.
3386 // See how long it took.
3387 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003388 final int REGISTER_TIME_LIMIT_MS = 200;
3389 final int CONNECT_TIME_LIMIT_MS = 60;
3390 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003391 final int UNREGISTER_TIME_LIMIT_MS = 20;
3392
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003393 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3394 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3395 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3396 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3397
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003398 for (int i = 0; i < NUM_REQUESTS; i++) {
3399 callbacks[i] = new NetworkCallback() {
3400 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3401 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3402 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003403 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003404
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003405 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003406 for (NetworkCallback cb : callbacks) {
3407 mCm.registerNetworkCallback(request, cb);
3408 }
3409 });
3410
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003411 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003412 // Don't request that the network validate, because otherwise connect() will block until
3413 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3414 // and we won't actually measure anything.
3415 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003416
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003417 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003418 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003419 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003420 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3421 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3422 onAvailableDispatchingDuration));
3423 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3424 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3425 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003426
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003427 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003428 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003429 mWiFiNetworkAgent.adjustScore(40);
3430 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003431
3432 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003433 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003434 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003435 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3436 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3437 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3438 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3439 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003440
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003441 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003442 for (NetworkCallback cb : callbacks) {
3443 mCm.unregisterNetworkCallback(cb);
3444 }
3445 });
3446 }
3447
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003448 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003449 public void testMobileDataAlwaysOn() throws Exception {
paulhu86e23eb2019-11-05 18:05:05 +08003450 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003451 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3452 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3453 .addTransportType(TRANSPORT_CELLULAR).build();
3454 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3455
3456 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3457 handlerThread.start();
3458 NetworkCapabilities filter = new NetworkCapabilities()
3459 .addTransportType(TRANSPORT_CELLULAR)
3460 .addCapability(NET_CAPABILITY_INTERNET);
3461 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3462 mServiceContext, "testFactory", filter);
3463 testFactory.setScoreFilter(40);
3464
3465 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003466 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003467 testFactory.register();
3468 testFactory.waitForNetworkRequests(1);
3469 assertTrue(testFactory.getMyStartRequested());
3470
3471 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003472 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003473 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3474 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003475 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003476 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003477 assertFalse(testFactory.getMyStartRequested());
3478
3479 ContentResolver cr = mServiceContext.getContentResolver();
3480
3481 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003482 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003483 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003484 testFactory.waitForNetworkRequests(2);
3485 assertTrue(testFactory.getMyStartRequested());
3486
3487 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003488 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003489 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003490 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003491 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003492 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003493 testFactory.waitForNetworkRequests(2);
3494 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3495
3496 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003497 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003498 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003499 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003500
3501 // Turn off mobile data always on and expect the request to disappear...
3502 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003503 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003504 testFactory.waitForNetworkRequests(1);
3505
3506 // ... and cell data to be torn down.
Chalard Jean059c4262019-09-30 17:51:12 +09003507 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003508 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003509
Lorenzo Colittif1080a92020-03-02 19:46:35 +09003510 testFactory.terminate();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003511 mCm.unregisterNetworkCallback(cellNetworkCallback);
3512 handlerThread.quit();
3513 }
3514
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003515 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003516 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003517 final ContentResolver cr = mServiceContext.getContentResolver();
3518 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3519
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003520 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003521 String[] values = new String[] {null, "0", "1"};
3522 for (int i = 0; i < values.length; i++) {
3523 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003524 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003525 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003526 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003527 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003528 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003529 }
3530
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003531 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003532
3533 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003534 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003535 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003536 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003537 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003538
3539 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003540 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003541 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003542 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003543 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003544
3545 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003546 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003547 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003548 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003549 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003550 }
3551
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003552 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003553 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003554 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003555
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003556 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003557 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003558
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003559 // File a request for cell to ensure it doesn't go down.
3560 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3561 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3562 .addTransportType(TRANSPORT_CELLULAR).build();
3563 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3564
3565 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3566 mCm.registerDefaultNetworkCallback(defaultCallback);
3567
3568 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3569 .addTransportType(TRANSPORT_WIFI)
3570 .addCapability(NET_CAPABILITY_VALIDATED)
3571 .build();
3572 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3573 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3574
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003575 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003576 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003577
3578 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003579 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003580 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003581 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3582 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003583 Network cellNetwork = mCellNetworkAgent.getNetwork();
3584
3585 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003586 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003587 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003588 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3589 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003590 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3591
3592 // Fail validation on wifi.
lucaslin783f2212019-10-22 18:27:33 +08003593 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003594 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003595 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003596 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003597
3598 // Because avoid bad wifi is off, we don't switch to cellular.
3599 defaultCallback.assertNoCallback();
3600 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3601 NET_CAPABILITY_VALIDATED));
3602 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3603 NET_CAPABILITY_VALIDATED));
3604 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3605
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003606 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3607 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003608 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3609 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003610 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003611 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3612
3613 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003614 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3615 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003616 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003617 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3618
3619 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3620 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003621 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003622 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3623 NET_CAPABILITY_VALIDATED));
3624 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3625 NET_CAPABILITY_VALIDATED));
3626 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3627
3628 // Disconnect and reconnect wifi to clear the one-time switch above.
3629 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003630 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003631 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003632 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3633 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003634 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3635
3636 // Fail validation on wifi and expect the dialog to appear.
lucaslin783f2212019-10-22 18:27:33 +08003637 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003638 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003639 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003640 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003641
3642 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003643 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003644 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003645
3646 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003647 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003648 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3649 NET_CAPABILITY_VALIDATED));
3650 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3651 NET_CAPABILITY_VALIDATED));
3652 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3653
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003654 // Simulate the user turning the cellular fallback setting off and then on.
3655 // We switch to wifi and then to cell.
3656 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003657 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003658 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003659 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3660 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003661 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003662 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003663 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3664
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003665 // If cell goes down, we switch to wifi.
3666 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003667 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003668 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003669 validatedWifiCallback.assertNoCallback();
3670
3671 mCm.unregisterNetworkCallback(cellNetworkCallback);
3672 mCm.unregisterNetworkCallback(validatedWifiCallback);
3673 mCm.unregisterNetworkCallback(defaultCallback);
3674 }
3675
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003676 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003677 public void testMeteredMultipathPreferenceSetting() throws Exception {
3678 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003679 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3680
3681 for (int config : Arrays.asList(0, 3, 2)) {
3682 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003683 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003684 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003685 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003686 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003687
3688 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3689 String msg = String.format("config=%d, setting=%s", config, setting);
3690 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3691 }
3692 }
3693 }
3694
Erik Kline3841a482015-11-25 12:49:38 +09003695 /**
3696 * Validate that a satisfied network request does not trigger onUnavailable() once the
3697 * time-out period expires.
3698 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003699 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003700 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003701 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3702 NetworkCapabilities.TRANSPORT_WIFI).build();
3703 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003704 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003705
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003706 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003707 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003708 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003709 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003710
3711 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003712 networkCallback.assertNoCallback();
3713 }
3714
3715 /**
3716 * Validate that a satisfied network request followed by a disconnected (lost) network does
3717 * not trigger onUnavailable() once the time-out period expires.
3718 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003719 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003720 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003721 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3722 NetworkCapabilities.TRANSPORT_WIFI).build();
3723 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003724 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003725
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003726 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003727 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003728 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003729 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003730 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003731 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003732
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003733 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003734 networkCallback.assertNoCallback();
3735 }
3736
3737 /**
3738 * Validate that when a time-out is specified for a network request the onUnavailable()
3739 * callback is called when time-out expires. Then validate that if network request is
3740 * (somehow) satisfied - the callback isn't called later.
3741 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003742 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003743 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003744 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3745 NetworkCapabilities.TRANSPORT_WIFI).build();
3746 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003747 final int timeoutMs = 10;
3748 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003749
3750 // pass timeout and validate that UNAVAILABLE is called
Automerger Merge Worker6b606b32020-03-14 05:13:42 +00003751 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
Erik Kline3841a482015-11-25 12:49:38 +09003752
3753 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003754 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003755 mWiFiNetworkAgent.connect(false);
3756 networkCallback.assertNoCallback();
3757 }
3758
3759 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003760 * Validate that when a network request is unregistered (cancelled), no posterior event can
3761 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003762 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003763 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003764 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003765 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3766 NetworkCapabilities.TRANSPORT_WIFI).build();
3767 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003768 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003769
Hugo Benichidfb559a2016-12-20 14:57:49 +09003770 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003771 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003772 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3773 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003774 networkCallback.assertNoCallback();
3775
3776 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003777 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003778 mWiFiNetworkAgent.connect(false);
3779 networkCallback.assertNoCallback();
3780 }
3781
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003782 @Test
3783 public void testUnfulfillableNetworkRequest() throws Exception {
3784 runUnfulfillableNetworkRequest(false);
3785 }
3786
3787 @Test
3788 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3789 runUnfulfillableNetworkRequest(true);
3790 }
3791
Etan Cohenddb720a2019-01-08 12:09:18 -08003792 /**
3793 * Validate the callback flow for a factory releasing a request as unfulfillable.
3794 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003795 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003796 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3797 NetworkCapabilities.TRANSPORT_WIFI).build();
3798 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3799
3800 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3801 handlerThread.start();
3802 NetworkCapabilities filter = new NetworkCapabilities()
3803 .addTransportType(TRANSPORT_WIFI)
3804 .addCapability(NET_CAPABILITY_INTERNET);
3805 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3806 mServiceContext, "testFactory", filter);
3807 testFactory.setScoreFilter(40);
3808
3809 // Register the factory and expect it to receive the default request.
Etan Cohenae574a82019-01-08 12:09:18 -08003810 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003811 testFactory.register();
3812 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3813
3814 assertEquals(1, requests.size()); // have 1 request at this point
3815 int origRequestId = requests.valueAt(0).requestId;
3816
3817 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003818 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003819 mCm.requestNetwork(nr, networkCallback);
3820 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3821
3822 int newRequestId = 0;
3823 for (int i = 0; i < requests.size(); ++i) {
3824 if (requests.valueAt(i).requestId != origRequestId) {
3825 newRequestId = requests.valueAt(i).requestId;
3826 break;
3827 }
3828 }
3829
Etan Cohen22e0fc12019-05-23 08:16:20 -07003830 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003831 if (preUnregister) {
3832 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003833
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003834 // Simulate the factory releasing the request as unfulfillable: no-op since
3835 // the callback has already been unregistered (but a test that no exceptions are
3836 // thrown).
3837 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3838 } else {
3839 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003840 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3841
Automerger Merge Worker6b606b32020-03-14 05:13:42 +00003842 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003843 testFactory.waitForRequests();
3844
3845 // unregister network callback - a no-op (since already freed by the
3846 // on-unavailable), but should not fail or throw exceptions.
3847 mCm.unregisterNetworkCallback(networkCallback);
3848 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003849
Lorenzo Colittif1080a92020-03-02 19:46:35 +09003850 testFactory.terminate();
Etan Cohenddb720a2019-01-08 12:09:18 -08003851 handlerThread.quit();
3852 }
3853
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003854 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3855
Chalard Jeane7b24752019-06-20 16:01:19 +09003856 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003857
3858 private class CallbackValue {
3859 public CallbackType callbackType;
3860 public int error;
3861
3862 public CallbackValue(CallbackType type) {
3863 this.callbackType = type;
3864 this.error = PacketKeepalive.SUCCESS;
3865 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3866 }
3867
3868 public CallbackValue(CallbackType type, int error) {
3869 this.callbackType = type;
3870 this.error = error;
3871 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3872 }
3873
3874 @Override
3875 public boolean equals(Object o) {
3876 return o instanceof CallbackValue &&
3877 this.callbackType == ((CallbackValue) o).callbackType &&
3878 this.error == ((CallbackValue) o).error;
3879 }
3880
3881 @Override
3882 public String toString() {
3883 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3884 }
3885 }
3886
junyulai7c469172019-01-16 20:23:34 +08003887 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003888
3889 @Override
3890 public void onStarted() {
3891 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3892 }
3893
3894 @Override
3895 public void onStopped() {
3896 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3897 }
3898
3899 @Override
3900 public void onError(int error) {
3901 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3902 }
3903
Chalard Jeane7b24752019-06-20 16:01:19 +09003904 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3905 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003906 }
3907
Chalard Jeane7b24752019-06-20 16:01:19 +09003908 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003909 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3910 }
3911
Chalard Jeane7b24752019-06-20 16:01:19 +09003912 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003913 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3914 }
3915
Chalard Jeane7b24752019-06-20 16:01:19 +09003916 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003917 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3918 }
3919 }
3920
junyulai48eac1d42018-12-27 17:25:29 +08003921 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3922
3923 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3924
3925 private class CallbackValue {
3926 public CallbackType callbackType;
3927 public int error;
3928
3929 CallbackValue(CallbackType type) {
3930 this.callbackType = type;
3931 this.error = SocketKeepalive.SUCCESS;
3932 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3933 }
3934
3935 CallbackValue(CallbackType type, int error) {
3936 this.callbackType = type;
3937 this.error = error;
3938 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3939 }
3940
3941 @Override
3942 public boolean equals(Object o) {
3943 return o instanceof CallbackValue
3944 && this.callbackType == ((CallbackValue) o).callbackType
3945 && this.error == ((CallbackValue) o).error;
3946 }
3947
3948 @Override
3949 public String toString() {
3950 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3951 error);
3952 }
3953 }
3954
3955 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003956 private final Executor mExecutor;
3957
3958 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3959 mExecutor = executor;
3960 }
junyulai48eac1d42018-12-27 17:25:29 +08003961
3962 @Override
3963 public void onStarted() {
3964 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3965 }
3966
3967 @Override
3968 public void onStopped() {
3969 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3970 }
3971
3972 @Override
3973 public void onError(int error) {
3974 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3975 }
3976
Chalard Jeane7b24752019-06-20 16:01:19 +09003977 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3978 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3979
junyulai48eac1d42018-12-27 17:25:29 +08003980 }
3981
Chalard Jeane7b24752019-06-20 16:01:19 +09003982 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003983 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3984 }
3985
Chalard Jeane7b24752019-06-20 16:01:19 +09003986 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003987 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3988 }
3989
Chalard Jeane7b24752019-06-20 16:01:19 +09003990 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003991 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3992 }
junyulai7c469172019-01-16 20:23:34 +08003993
3994 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003995 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08003996 CallbackValue cv = mCallbacks.peek();
3997 assertNull("Unexpected callback: " + cv, cv);
3998 }
junyulai48eac1d42018-12-27 17:25:29 +08003999 }
4000
Chalard Jeane7b24752019-06-20 16:01:19 +09004001 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004002 // Ensure the network is disconnected before we do anything.
4003 if (mWiFiNetworkAgent != null) {
4004 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
4005 }
4006
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004007 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09004008 ConditionVariable cv = registerConnectivityBroadcast(1);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004009 mWiFiNetworkAgent.connect(true);
4010 waitFor(cv);
4011 verifyActiveNetwork(TRANSPORT_WIFI);
4012 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09004013 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004014 return mWiFiNetworkAgent.getNetwork();
4015 }
4016
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004017 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07004018 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004019 public void testPacketKeepalives() throws Exception {
4020 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4021 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4022 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4023 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4024 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4025
Nathan Harold63dd8132018-02-14 13:09:45 -08004026 final int validKaInterval = 15;
4027 final int invalidKaInterval = 9;
4028
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004029 LinkProperties lp = new LinkProperties();
4030 lp.setInterfaceName("wlan12");
4031 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4032 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4033 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4034 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4035
4036 Network notMyNet = new Network(61234);
4037 Network myNet = connectKeepaliveNetwork(lp);
4038
4039 TestKeepaliveCallback callback = new TestKeepaliveCallback();
4040 PacketKeepalive ka;
4041
4042 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08004043 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004044 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4045
Nathan Harold63dd8132018-02-14 13:09:45 -08004046 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004047 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4048
Nathan Harold63dd8132018-02-14 13:09:45 -08004049 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004050 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4051
Nathan Harold63dd8132018-02-14 13:09:45 -08004052 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004053 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4054
Nathan Harold63dd8132018-02-14 13:09:45 -08004055 // NAT-T is only supported for IPv4.
4056 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4057 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004058
Nathan Harold63dd8132018-02-14 13:09:45 -08004059 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004060 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4061
Nathan Harold63dd8132018-02-14 13:09:45 -08004062 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004063 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4064
Nathan Harold63dd8132018-02-14 13:09:45 -08004065 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004066 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4067
Nathan Harold63dd8132018-02-14 13:09:45 -08004068 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004069 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4070
4071 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004072 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08004073 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004074 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004075 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004076 ka.stop();
4077 callback.expectStopped();
4078
4079 // Check that deleting the IP address stops the keepalive.
4080 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08004081 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004082 callback.expectStarted();
4083 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4084 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4085 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4086 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4087 mWiFiNetworkAgent.sendLinkProperties(lp);
4088
4089 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004090 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004091 callback.expectStarted();
4092 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004093 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004094 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4095
4096 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004097 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004098 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004099 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004100 ka.stop();
4101
4102 // Reconnect.
4103 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004104 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004105
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004106 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4107 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004108 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004109 callback.expectStarted();
4110
4111 // The second one gets slot 2.
4112 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4113 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004114 PacketKeepalive ka2 = mCm.startNattKeepalive(
4115 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004116 callback2.expectStarted();
4117
4118 // Now stop the first one and create a third. This also gets slot 1.
4119 ka.stop();
4120 callback.expectStopped();
4121
4122 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4123 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004124 PacketKeepalive ka3 = mCm.startNattKeepalive(
4125 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004126 callback3.expectStarted();
4127
4128 ka2.stop();
4129 callback2.expectStopped();
4130
4131 ka3.stop();
4132 callback3.expectStopped();
4133 }
Udam Sainib7c24872016-01-04 12:16:14 -08004134
Xiao Maa4637112019-02-07 15:03:57 +09004135 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09004136 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
4137 throws Exception {
junyulai06835112019-01-03 18:50:15 +08004138 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004139 final Executor executorInline = (Runnable r) -> r.run();
4140 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08004141 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004142 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004143 }
junyulai06835112019-01-03 18:50:15 +08004144
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004145 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004146 public void testNattSocketKeepalives() throws Exception {
4147 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4148 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08004149 }
4150
4151 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004152 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08004153 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004154 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004155 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4156 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4157 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4158 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4159 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4160
4161 final int validKaInterval = 15;
4162 final int invalidKaInterval = 9;
4163
4164 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004165 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4166 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004167
junyulai48eac1d42018-12-27 17:25:29 +08004168 LinkProperties lp = new LinkProperties();
4169 lp.setInterfaceName("wlan12");
4170 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4171 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4172 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4173 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4174
4175 Network notMyNet = new Network(61234);
4176 Network myNet = connectKeepaliveNetwork(lp);
4177
junyulai7c469172019-01-16 20:23:34 +08004178 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004179
4180 // Attempt to start keepalives with invalid parameters and check for errors.
4181 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004182 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4183 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4184 ka.start(validKaInterval);
4185 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4186 }
junyulai48eac1d42018-12-27 17:25:29 +08004187
4188 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004189 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4190 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4191 ka.start(invalidKaInterval);
4192 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4193 }
junyulai48eac1d42018-12-27 17:25:29 +08004194
4195 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004196 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4197 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4198 ka.start(validKaInterval);
4199 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4200 }
junyulai48eac1d42018-12-27 17:25:29 +08004201
4202 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004203 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4204 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4205 ka.start(validKaInterval);
4206 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4207 }
junyulai48eac1d42018-12-27 17:25:29 +08004208
4209 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004210 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4211 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4212 ka.start(validKaInterval);
4213 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4214 }
junyulai48eac1d42018-12-27 17:25:29 +08004215
4216 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004217 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4218 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4219 ka.start(validKaInterval);
4220 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4221 }
junyulai48eac1d42018-12-27 17:25:29 +08004222
4223 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004224 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004225 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4226 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4227 ka.start(validKaInterval);
4228 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004229 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004230 ka.stop();
4231 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004232
junyulai0c666972019-03-04 22:45:36 +08004233 // Check that keepalive could be restarted.
4234 ka.start(validKaInterval);
4235 callback.expectStarted();
4236 ka.stop();
4237 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004238
junyulai0c666972019-03-04 22:45:36 +08004239 // Check that keepalive can be restarted without waiting for callback.
4240 ka.start(validKaInterval);
4241 callback.expectStarted();
4242 ka.stop();
4243 ka.start(validKaInterval);
4244 callback.expectStopped();
4245 callback.expectStarted();
4246 ka.stop();
4247 callback.expectStopped();
4248 }
junyulai7c469172019-01-16 20:23:34 +08004249
junyulai48eac1d42018-12-27 17:25:29 +08004250 // Check that deleting the IP address stops the keepalive.
4251 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004252 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4253 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4254 ka.start(validKaInterval);
4255 callback.expectStarted();
4256 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4257 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4258 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4259 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4260 mWiFiNetworkAgent.sendLinkProperties(lp);
4261 }
junyulai48eac1d42018-12-27 17:25:29 +08004262
4263 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004264 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4265 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4266 ka.start(validKaInterval);
4267 callback.expectStarted();
4268 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004269 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004270 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004271
junyulai0c666972019-03-04 22:45:36 +08004272 // ... and that stopping it after that has no adverse effects.
4273 waitForIdle();
4274 final Network myNetAlias = myNet;
4275 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4276 ka.stop();
4277 callback.assertNoCallback();
4278 }
junyulai48eac1d42018-12-27 17:25:29 +08004279
4280 // Reconnect.
4281 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004282 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08004283
4284 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4285 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004286 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004287 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4288 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4289 ka.start(validKaInterval);
4290 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004291
junyulai0c666972019-03-04 22:45:36 +08004292 // The second one gets slot 2.
4293 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004294 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4295 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004296 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4297 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4298 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4299 ka2.start(validKaInterval);
4300 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004301
junyulai0c666972019-03-04 22:45:36 +08004302 ka.stop();
4303 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004304
junyulai0c666972019-03-04 22:45:36 +08004305 ka2.stop();
4306 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004307
junyulai0c666972019-03-04 22:45:36 +08004308 testSocket.close();
4309 testSocket2.close();
4310 }
4311 }
junyulai06835112019-01-03 18:50:15 +08004312
junyulai15178152019-03-27 11:00:37 +08004313 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004314 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4315 // assertFalse(isUdpPortInUse(srcPort));
4316 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004317
junyulai06835112019-01-03 18:50:15 +08004318 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004319 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004320 mWiFiNetworkAgent = null;
4321 }
4322
4323 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004324 public void testTcpSocketKeepalives() throws Exception {
4325 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004326 }
4327
4328 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4329 final int srcPortV4 = 12345;
4330 final int srcPortV6 = 23456;
4331 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4332 final InetAddress myIPv6 = InetAddress.getByName("::1");
4333
4334 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004335
4336 final LinkProperties lp = new LinkProperties();
4337 lp.setInterfaceName("wlan12");
4338 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4339 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4340 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4341 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4342
4343 final Network notMyNet = new Network(61234);
4344 final Network myNet = connectKeepaliveNetwork(lp);
4345
4346 final Socket testSocketV4 = new Socket();
4347 final Socket testSocketV6 = new Socket();
4348
junyulai7c469172019-01-16 20:23:34 +08004349 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004350
4351 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4352 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004353 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4354 notMyNet, testSocketV4, executor, callback)) {
4355 ka.start(validKaInterval);
4356 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4357 }
Xiao Maa4637112019-02-07 15:03:57 +09004358
4359 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004360 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4361 myNet, testSocketV4, executor, callback)) {
4362 ka.start(validKaInterval);
4363 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4364 }
Xiao Maa4637112019-02-07 15:03:57 +09004365
4366 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004367 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4368 myNet, testSocketV6, executor, callback)) {
4369 ka.start(validKaInterval);
4370 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4371 }
Xiao Maa4637112019-02-07 15:03:57 +09004372
4373 // Bind the socket address
4374 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4375 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4376
4377 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004378 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4379 myNet, testSocketV4, executor, callback)) {
4380 ka.start(validKaInterval);
4381 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4382 }
Xiao Maa4637112019-02-07 15:03:57 +09004383
4384 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004385 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4386 myNet, testSocketV6, executor, callback)) {
4387 ka.start(validKaInterval);
4388 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4389 }
Xiao Maa4637112019-02-07 15:03:57 +09004390
4391 testSocketV4.close();
4392 testSocketV6.close();
4393
4394 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004395 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004396 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004397 }
4398
junyulai0c666972019-03-04 22:45:36 +08004399 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004400 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4401 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4402 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4403 final int validKaInterval = 15;
4404
4405 // Prepare the target network.
4406 LinkProperties lp = new LinkProperties();
4407 lp.setInterfaceName("wlan12");
4408 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4409 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4410 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004411 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4412 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004413
4414 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4415
4416 // Prepare the target file descriptor, keep only one instance.
4417 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004418 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4419 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004420 final ParcelFileDescriptor testPfd =
4421 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4422 testSocket.close();
4423 assertTrue(isUdpPortInUse(srcPort));
4424
4425 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4426 // block.
4427 try (SocketKeepalive ka = mCm.createNattKeepalive(
4428 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4429 ka.start(validKaInterval);
4430 callback.expectStarted();
4431 ka.stop();
4432 callback.expectStopped();
4433 }
4434
4435 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4436 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4437 // address.
4438 assertTrue(isUdpPortInUse(srcPort));
4439 final InetSocketAddress sa =
4440 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4441 assertEquals(anyIPv4, sa.getAddress());
4442
4443 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004444 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4445 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004446
4447 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004448 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004449 mWiFiNetworkAgent = null;
4450 }
4451
4452 private static boolean isUdpPortInUse(int port) {
4453 try (DatagramSocket ignored = new DatagramSocket(port)) {
4454 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004455 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004456 return true;
4457 }
4458 }
4459
junyulai48eac1d42018-12-27 17:25:29 +08004460 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004461 public void testGetCaptivePortalServerUrl() throws Exception {
4462 String url = mCm.getCaptivePortalServerUrl();
4463 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4464 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004465
4466 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004467 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004468 synchronized(sLock) {
4469 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004470 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004471 }
4472 return sNetwork != null;
4473 }
4474 }
4475
Chalard Jeane7b24752019-06-20 16:01:19 +09004476 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004477 synchronized(sLock) {
4478 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004479 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004480 }
4481 return sNetwork == null;
4482 }
4483 }
4484 }
4485
4486 private void assertPinnedToWifiWithCellDefault() {
4487 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4488 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4489 }
4490
4491 private void assertPinnedToWifiWithWifiDefault() {
4492 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4493 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4494 }
4495
4496 private void assertNotPinnedToWifi() {
4497 assertNull(mCm.getBoundNetworkForProcess());
4498 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4499 }
4500
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004501 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004502 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004503 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4504 .addTransportType(TRANSPORT_WIFI)
4505 .build();
4506 assertNull(mCm.getBoundNetworkForProcess());
4507
4508 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4509 assertNull(mCm.getBoundNetworkForProcess());
4510
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004511 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004512 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004513 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004514 mWiFiNetworkAgent.connect(false);
4515
4516 // When wi-fi connects, expect to be pinned.
4517 assertTrue(TestNetworkPinner.awaitPin(100));
4518 assertPinnedToWifiWithCellDefault();
4519
4520 // Disconnect and expect the pin to drop.
4521 mWiFiNetworkAgent.disconnect();
4522 assertTrue(TestNetworkPinner.awaitUnpin(100));
4523 assertNotPinnedToWifi();
4524
4525 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004526 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004527 mWiFiNetworkAgent.connect(false);
4528 assertFalse(TestNetworkPinner.awaitPin(100));
4529 assertNotPinnedToWifi();
4530
4531 // Pinning while connected causes the pin to take effect immediately.
4532 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4533 assertTrue(TestNetworkPinner.awaitPin(100));
4534 assertPinnedToWifiWithCellDefault();
4535
4536 // Explicitly unpin and expect to use the default network again.
4537 TestNetworkPinner.unpin();
4538 assertNotPinnedToWifi();
4539
4540 // Disconnect cell and wifi.
Chalard Jean407deb72019-11-19 16:14:30 +09004541 ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004542 mCellNetworkAgent.disconnect();
4543 mWiFiNetworkAgent.disconnect();
4544 waitFor(cv);
4545
4546 // Pinning takes effect even if the pinned network is the default when the pin is set...
4547 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004548 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004549 mWiFiNetworkAgent.connect(false);
4550 assertTrue(TestNetworkPinner.awaitPin(100));
4551 assertPinnedToWifiWithWifiDefault();
4552
4553 // ... and is maintained even when that network is no longer the default.
Chalard Jean407deb72019-11-19 16:14:30 +09004554 cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004555 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004556 mCellNetworkAgent.connect(true);
4557 waitFor(cv);
4558 assertPinnedToWifiWithCellDefault();
4559 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004560
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004561 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004562 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004563 // We can only have 99 callbacks, because MultipathPolicyTracker is
4564 // already one of them.
4565 final int MAX_REQUESTS = 99;
4566 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004567 final int INTENTS = 10;
4568 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4569
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004570 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004571 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004572
Hugo Benichi893a7622017-09-29 09:34:08 +09004573 int j = 0;
4574 while (j++ < CALLBACKS / 2) {
4575 NetworkCallback cb = new NetworkCallback();
4576 mCm.requestNetwork(networkRequest, cb);
4577 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004578 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004579 while (j++ < CALLBACKS) {
4580 NetworkCallback cb = new NetworkCallback();
4581 mCm.registerNetworkCallback(networkRequest, cb);
4582 registered.add(cb);
4583 }
4584 j = 0;
4585 while (j++ < INTENTS / 2) {
4586 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4587 mCm.requestNetwork(networkRequest, pi);
4588 registered.add(pi);
4589 }
4590 while (j++ < INTENTS) {
4591 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4592 mCm.registerNetworkCallback(networkRequest, pi);
4593 registered.add(pi);
4594 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004595
Hugo Benichi893a7622017-09-29 09:34:08 +09004596 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004597 assertThrows(TooManyRequestsException.class, () ->
4598 mCm.requestNetwork(networkRequest, new NetworkCallback())
4599 );
4600 assertThrows(TooManyRequestsException.class, () ->
4601 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4602 );
4603 assertThrows(TooManyRequestsException.class, () ->
4604 mCm.requestNetwork(networkRequest,
4605 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4606 );
4607 assertThrows(TooManyRequestsException.class, () ->
4608 mCm.registerNetworkCallback(networkRequest,
4609 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4610 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004611
Hugo Benichi893a7622017-09-29 09:34:08 +09004612 for (Object o : registered) {
4613 if (o instanceof NetworkCallback) {
4614 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004615 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004616 if (o instanceof PendingIntent) {
4617 mCm.unregisterNetworkCallback((PendingIntent)o);
4618 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004619 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004620 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004621
4622 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4623 for (int i = 0; i < MAX_REQUESTS; i++) {
4624 NetworkCallback networkCallback = new NetworkCallback();
4625 mCm.requestNetwork(networkRequest, networkCallback);
4626 mCm.unregisterNetworkCallback(networkCallback);
4627 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004628 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004629
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004630 for (int i = 0; i < MAX_REQUESTS; i++) {
4631 NetworkCallback networkCallback = new NetworkCallback();
4632 mCm.registerNetworkCallback(networkRequest, networkCallback);
4633 mCm.unregisterNetworkCallback(networkCallback);
4634 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004635 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004636
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004637 for (int i = 0; i < MAX_REQUESTS; i++) {
4638 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004639 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004640 mCm.requestNetwork(networkRequest, pendingIntent);
4641 mCm.unregisterNetworkCallback(pendingIntent);
4642 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004643 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004644
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004645 for (int i = 0; i < MAX_REQUESTS; i++) {
4646 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004647 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004648 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4649 mCm.unregisterNetworkCallback(pendingIntent);
4650 }
4651 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004652
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004653 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004654 public void testNetworkInfoOfTypeNone() throws Exception {
Chalard Jean407deb72019-11-19 16:14:30 +09004655 ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004656
4657 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004658 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004659 assertNull(mCm.getActiveNetworkInfo());
4660
4661 Network[] allNetworks = mCm.getAllNetworks();
4662 assertLength(1, allNetworks);
4663 Network network = allNetworks[0];
4664 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4665 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4666
4667 final NetworkRequest request =
4668 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4669 final TestNetworkCallback callback = new TestNetworkCallback();
4670 mCm.registerNetworkCallback(request, callback);
4671
Hugo Benichic1014502017-07-19 10:10:52 +09004672 // Bring up wifi aware network.
lucaslin783f2212019-10-22 18:27:33 +08004673 wifiAware.connect(false, false, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004674 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004675
4676 assertNull(mCm.getActiveNetworkInfo());
4677 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004678 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004679 // of this test. Fix it and uncomment the assert below.
4680 //assertEmpty(mCm.getAllNetworkInfo());
4681
Hugo Benichic1014502017-07-19 10:10:52 +09004682 // Disconnect wifi aware network.
4683 wifiAware.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09004684 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004685 mCm.unregisterNetworkCallback(callback);
4686
4687 verifyNoNetwork();
4688 if (broadcastCV.block(10)) {
4689 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4690 }
4691 }
4692
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004693 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004694 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4695 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4696 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4697 assertNull(mCm.getNetworkForType(TYPE_NONE));
4698 assertNull(mCm.getLinkProperties(TYPE_NONE));
4699 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4700
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004701 assertThrows(IllegalArgumentException.class,
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004702 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004703
4704 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004705 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4706 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004707 // TODO: let test context have configuration application target sdk version
4708 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004709 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4710 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4711 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004712 }
4713
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004714 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004715 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004716 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4717 .addTransportType(TRANSPORT_WIFI).build();
4718 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4719 mCm.registerNetworkCallback(networkRequest, networkCallback);
4720
4721 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004722 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004723 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4724 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4725 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4726 lp.addLinkAddress(myIpv4Address);
4727 lp.addRoute(myIpv4DefaultRoute);
4728
4729 // Verify direct routes are added when network agent is first registered in
4730 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004731 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004732 networkAgent.connect(true);
Chalard Jean059c4262019-09-30 17:51:12 +09004733 networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
4734 networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
4735 CallbackEntry.LinkPropertiesChanged cbi =
4736 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004737 networkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004738 networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004739 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4740 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004741 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004742 Arrays.asList(myIpv4DefaultRoute));
4743 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4744 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4745
4746 // Verify direct routes are added during subsequent link properties updates.
4747 LinkProperties newLp = new LinkProperties(lp);
4748 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4749 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4750 newLp.addLinkAddress(myIpv6Address1);
4751 newLp.addLinkAddress(myIpv6Address2);
4752 networkAgent.sendLinkProperties(newLp);
Chalard Jean059c4262019-09-30 17:51:12 +09004753 cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004754 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004755 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004756 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4757 Arrays.asList(myIpv4DefaultRoute));
4758 mCm.unregisterNetworkCallback(networkCallback);
4759 }
4760
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004761 @Test
4762 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004763 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4764 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004765
Varun Anandd33cbc62019-02-07 14:13:13 -08004766 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4767 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4768
4769 LinkProperties cellLp = new LinkProperties();
4770 cellLp.setInterfaceName(MOBILE_IFNAME);
4771 LinkProperties wifiLp = new LinkProperties();
4772 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004773
4774 // Simple connection should have updated ifaces
4775 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004776 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004777 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004778 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004779 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4780 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004781 reset(mStatsService);
4782
4783 // Default network switch should update ifaces.
4784 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004785 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004786 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004787 assertEquals(wifiLp, mService.getActiveLinkProperties());
4788 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004789 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4790 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004791 reset(mStatsService);
4792
4793 // Disconnect should update ifaces.
4794 mWiFiNetworkAgent.disconnect();
4795 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004796 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004797 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4798 eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004799 reset(mStatsService);
4800
4801 // Metered change should update ifaces
4802 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4803 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004804 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004805 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4806 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004807 reset(mStatsService);
4808
4809 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4810 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004811 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004812 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4813 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004814 reset(mStatsService);
4815
4816 // Captive portal change shouldn't update ifaces
4817 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4818 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004819 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004820 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4821 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004822 reset(mStatsService);
4823
4824 // Roaming change should update ifaces
4825 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4826 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004827 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004828 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4829 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004830 reset(mStatsService);
4831 }
4832
Erik Klinee89953b2018-01-11 16:11:10 +09004833 @Test
4834 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004835 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004836
4837 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004838 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004839
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004840 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09004841 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004842 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004843 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004844
4845 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004846 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004847 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4848 // "is-reachable" testing in order to not program netd with unreachable
4849 // nameservers that it might try repeated to validate.
4850 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004851 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4852 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004853 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004854 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4855 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004856 mCellNetworkAgent.sendLinkProperties(cellLp);
4857 mCellNetworkAgent.connect(false);
4858 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004859
4860 verify(mMockDnsResolver, times(1)).createNetworkCache(
4861 eq(mCellNetworkAgent.getNetwork().netId));
4862 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004863 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004864 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004865
4866 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4867 mCellNetworkAgent.sendLinkProperties(cellLp);
4868 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004869 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004870 mResolverParamsParcelCaptor.capture());
4871 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4872 assertEquals(1, resolvrParams.servers.length);
4873 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004874 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004875 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004876 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004877
4878 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4879 mCellNetworkAgent.sendLinkProperties(cellLp);
4880 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004881 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004882 mResolverParamsParcelCaptor.capture());
4883 resolvrParams = mResolverParamsParcelCaptor.getValue();
4884 assertEquals(2, resolvrParams.servers.length);
4885 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004886 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004887 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004888 assertEquals(2, resolvrParams.tlsServers.length);
4889 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004890 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004891 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004892
4893 final String TLS_SPECIFIER = "tls.example.com";
4894 final String TLS_SERVER6 = "2001:db8:53::53";
4895 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4896 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004897 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4898 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4899
Erik Kline117e7f32018-03-04 21:01:01 +09004900 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004901 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004902 mResolverParamsParcelCaptor.capture());
4903 resolvrParams = mResolverParamsParcelCaptor.getValue();
4904 assertEquals(2, resolvrParams.servers.length);
4905 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004906 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004907 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004908 }
4909
Erik Kline79c6d052018-03-21 07:18:33 -07004910 @Test
chenbruce5d955622020-02-20 14:28:31 +08004911 public void testDnsConfigurationTransTypesPushed() throws Exception {
4912 // Clear any interactions that occur as a result of CS starting up.
4913 reset(mMockDnsResolver);
4914
4915 final NetworkRequest request = new NetworkRequest.Builder()
4916 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4917 .build();
4918 final TestNetworkCallback callback = new TestNetworkCallback();
4919 mCm.registerNetworkCallback(request, callback);
4920
4921 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4922 mWiFiNetworkAgent.connect(false);
4923 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4924 verify(mMockDnsResolver, times(1)).createNetworkCache(
4925 eq(mWiFiNetworkAgent.getNetwork().netId));
4926 verify(mMockDnsResolver, times(2)).setResolverConfiguration(
4927 mResolverParamsParcelCaptor.capture());
4928 final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
4929 assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
4930 reset(mMockDnsResolver);
4931 }
4932
4933 @Test
lucaslin783f2212019-10-22 18:27:33 +08004934 public void testPrivateDnsNotification() throws Exception {
4935 NetworkRequest request = new NetworkRequest.Builder()
4936 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4937 .build();
4938 TestNetworkCallback callback = new TestNetworkCallback();
4939 mCm.registerNetworkCallback(request, callback);
4940 // Bring up wifi.
4941 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4942 mWiFiNetworkAgent.connect(false);
4943 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4944 // Private DNS resolution failed, checking if the notification will be shown or not.
4945 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4946 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4947 waitForIdle();
4948 // If network validation failed, NetworkMonitor will re-evaluate the network.
4949 // ConnectivityService should filter the redundant notification. This part is trying to
4950 // simulate that situation and check if ConnectivityService could filter that case.
4951 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4952 waitForIdle();
4953 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
4954 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4955 // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
4956 // shown.
4957 mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
4958 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4959 waitForIdle();
4960 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
4961 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
4962 // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
4963 // shown again.
4964 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4965 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4966 waitForIdle();
4967 verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
4968 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4969 }
4970
4971 @Test
Erik Kline79c6d052018-03-21 07:18:33 -07004972 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004973 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004974 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004975
4976 // The default on Android is opportunistic mode ("Automatic").
4977 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4978
dalyk1fcb7392018-03-05 12:42:22 -05004979 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4980 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4981 .addTransportType(TRANSPORT_CELLULAR).build();
4982 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4983
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004984 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07004985 waitForIdle();
4986 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004987 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004988 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004989
4990 final LinkProperties cellLp = new LinkProperties();
4991 cellLp.setInterfaceName(MOBILE_IFNAME);
4992 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4993 // "is-reachable" testing in order to not program netd with unreachable
4994 // nameservers that it might try repeated to validate.
4995 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4996 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4997 MOBILE_IFNAME));
4998 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4999 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
5000 MOBILE_IFNAME));
5001 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
5002 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
5003
5004 mCellNetworkAgent.sendLinkProperties(cellLp);
5005 mCellNetworkAgent.connect(false);
5006 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005007 verify(mMockDnsResolver, times(1)).createNetworkCache(
5008 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08005009 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005010 mResolverParamsParcelCaptor.capture());
5011 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5012 assertEquals(2, resolvrParams.tlsServers.length);
5013 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005014 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07005015 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08005016 assertEquals(2, resolvrParams.tlsServers.length);
5017 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005018 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08005019 reset(mMockDnsResolver);
Chalard Jean059c4262019-09-30 17:51:12 +09005020 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
5021 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05005022 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005023 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
5024 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
5025 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005026 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005027 assertFalse(cbi.getLp().isPrivateDnsActive());
5028 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07005029
5030 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005031 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005032 mResolverParamsParcelCaptor.capture());
5033 resolvrParams = mResolverParamsParcelCaptor.getValue();
5034 assertEquals(2, resolvrParams.servers.length);
5035 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005036 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08005037 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005038 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005039
5040 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08005041 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005042 mResolverParamsParcelCaptor.capture());
5043 resolvrParams = mResolverParamsParcelCaptor.getValue();
5044 assertEquals(2, resolvrParams.servers.length);
5045 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005046 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08005047 assertEquals(2, resolvrParams.tlsServers.length);
5048 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005049 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08005050 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005051 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005052
dalyk1fcb7392018-03-05 12:42:22 -05005053 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5054 // Can't test dns configuration for strict mode without properly mocking
5055 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean059c4262019-09-30 17:51:12 +09005056 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005057 mCellNetworkAgent);
5058 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005059 assertTrue(cbi.getLp().isPrivateDnsActive());
5060 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005061 }
5062
5063 @Test
5064 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5065 // The default on Android is opportunistic mode ("Automatic").
5066 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5067
5068 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5069 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5070 .addTransportType(TRANSPORT_CELLULAR).build();
5071 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5072
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005073 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05005074 waitForIdle();
5075 LinkProperties lp = new LinkProperties();
5076 mCellNetworkAgent.sendLinkProperties(lp);
5077 mCellNetworkAgent.connect(false);
5078 waitForIdle();
Chalard Jean059c4262019-09-30 17:51:12 +09005079 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
5080 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05005081 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005082 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
5083 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
5084 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005085 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005086 assertFalse(cbi.getLp().isPrivateDnsActive());
5087 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005088 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005089 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005090
5091 // Send a validation event for a server that is not part of the current
5092 // resolver config. The validation event should be ignored.
5093 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5094 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5095 cellNetworkCallback.assertNoCallback();
5096
5097 // Add a dns server to the LinkProperties.
5098 LinkProperties lp2 = new LinkProperties(lp);
5099 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5100 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean059c4262019-09-30 17:51:12 +09005101 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005102 mCellNetworkAgent);
5103 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005104 assertFalse(cbi.getLp().isPrivateDnsActive());
5105 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005106 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005107 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005108
5109 // Send a validation event containing a hostname that is not part of
5110 // the current resolver config. The validation event should be ignored.
5111 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5112 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5113 cellNetworkCallback.assertNoCallback();
5114
5115 // Send a validation event where validation failed.
5116 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5117 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5118 cellNetworkCallback.assertNoCallback();
5119
5120 // Send a validation event where validation succeeded for a server in
5121 // the current resolver config. A LinkProperties callback with updated
5122 // private dns fields should be sent.
5123 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5124 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean059c4262019-09-30 17:51:12 +09005125 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005126 mCellNetworkAgent);
5127 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005128 assertTrue(cbi.getLp().isPrivateDnsActive());
5129 assertNull(cbi.getLp().getPrivateDnsServerName());
5130 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005131
5132 // The private dns fields in LinkProperties should be preserved when
5133 // the network agent sends unrelated changes.
5134 LinkProperties lp3 = new LinkProperties(lp2);
5135 lp3.setMtu(1300);
5136 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean059c4262019-09-30 17:51:12 +09005137 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005138 mCellNetworkAgent);
5139 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005140 assertTrue(cbi.getLp().isPrivateDnsActive());
5141 assertNull(cbi.getLp().getPrivateDnsServerName());
5142 checkDnsServers(cbi.getLp(), dnsServers);
5143 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05005144
5145 // Removing the only validated server should affect the private dns
5146 // fields in LinkProperties.
5147 LinkProperties lp4 = new LinkProperties(lp3);
5148 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5149 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean059c4262019-09-30 17:51:12 +09005150 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005151 mCellNetworkAgent);
5152 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005153 assertFalse(cbi.getLp().isPrivateDnsActive());
5154 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005155 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005156 checkDnsServers(cbi.getLp(), dnsServers);
5157 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005158 }
5159
Rubin Xu1bb5c082017-09-05 18:40:49 +01005160 private void checkDirectlyConnectedRoutes(Object callbackObj,
5161 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5162 assertTrue(callbackObj instanceof LinkProperties);
5163 LinkProperties lp = (LinkProperties) callbackObj;
5164
5165 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5166 expectedRoutes.addAll(otherRoutes);
5167 for (LinkAddress address : linkAddresses) {
5168 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5169 // Duplicates in linkAddresses are considered failures
5170 assertTrue(expectedRoutes.add(localRoute));
5171 }
5172 List<RouteInfo> observedRoutes = lp.getRoutes();
5173 assertEquals(expectedRoutes.size(), observedRoutes.size());
5174 assertTrue(observedRoutes.containsAll(expectedRoutes));
5175 }
5176
dalyk1fcb7392018-03-05 12:42:22 -05005177 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5178 assertTrue(callbackObj instanceof LinkProperties);
5179 LinkProperties lp = (LinkProperties) callbackObj;
5180 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5181 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5182 }
5183
Chalard Jean0b214af2018-01-12 17:22:49 +09005184 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005185 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09005186 final int uid = Process.myUid();
5187
5188 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005189 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005190 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5191 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005192 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005193 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5194 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5195 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005196 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5197 .addTransportType(TRANSPORT_WIFI).build();
5198 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005199 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005200 .addTransportType(TRANSPORT_VPN).build();
5201 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005202 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005203 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5204 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005205 mCm.registerDefaultNetworkCallback(defaultCallback);
5206 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005207
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005208 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09005209 mWiFiNetworkAgent.connect(false);
5210
5211 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005212 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005213 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005214 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005215 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005216 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005217
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005218 final TestNetworkAgentWrapper
5219 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean0b214af2018-01-12 17:22:49 +09005220 final ArraySet<UidRange> ranges = new ArraySet<>();
5221 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005222 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5223 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005224 // VPN networks do not satisfy the default request and are automatically validated
5225 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005226 assertFalse(NetworkMonitorUtils.isValidationRequired(
5227 vpnNetworkAgent.getNetworkCapabilities()));
lucaslin783f2212019-10-22 18:27:33 +08005228 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005229
Chalard Jean0b214af2018-01-12 17:22:49 +09005230 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005231 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005232 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005233
5234 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005235 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005236 wifiNetworkCallback.assertNoCallback();
5237 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005238 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5239 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005240
Chalard Jean059c4262019-09-30 17:51:12 +09005241 genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005242 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005243 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
Chalard Jean059c4262019-09-30 17:51:12 +09005244 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005245 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005246
5247 ranges.clear();
5248 vpnNetworkAgent.setUids(ranges);
5249
Chalard Jean059c4262019-09-30 17:51:12 +09005250 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005251 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005252 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005253 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005254
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005255 // TODO : The default network callback should actually get a LOST call here (also see the
5256 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5257 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5258 // can't currently update their UIDs without disconnecting, so this does not matter too
5259 // much, but that is the reason the test here has to check for an update to the
5260 // capabilities instead of the expected LOST then AVAILABLE.
Chalard Jean059c4262019-09-30 17:51:12 +09005261 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005262
Chalard Jean0b214af2018-01-12 17:22:49 +09005263 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005264 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005265 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005266
5267 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005268 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005269 wifiNetworkCallback.assertNoCallback();
5270 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005271 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5272 // happen outside of the test, ConnectivityService does not rematch callbacks.
Chalard Jean059c4262019-09-30 17:51:12 +09005273 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005274
5275 mWiFiNetworkAgent.disconnect();
5276
Chalard Jean059c4262019-09-30 17:51:12 +09005277 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5278 genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5279 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005280 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005281 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005282
5283 vpnNetworkAgent.disconnect();
5284
Chalard Jean059c4262019-09-30 17:51:12 +09005285 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005286 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005287 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005288 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5289 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005290 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005291
5292 mCm.unregisterNetworkCallback(genericNetworkCallback);
5293 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5294 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005295 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005296 }
Chalard Jean26400492018-04-18 20:18:38 +09005297
5298 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005299 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09005300 final int uid = Process.myUid();
5301
5302 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5303 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005304
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005305 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09005306 mWiFiNetworkAgent.connect(true);
5307
5308 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5309 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5310
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005311 TestNetworkAgentWrapper
5312 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09005313 final ArraySet<UidRange> ranges = new ArraySet<>();
5314 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005315 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5316 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005317 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5318 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005319 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005320
5321 defaultCallback.assertNoCallback();
5322 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5323
5324 vpnNetworkAgent.disconnect();
5325 defaultCallback.assertNoCallback();
5326
Varun Anand4fa80e82019-02-06 10:13:38 -08005327 mCm.unregisterNetworkCallback(defaultCallback);
5328 }
5329
5330 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005331 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005332 final int uid = Process.myUid();
5333
5334 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5335 mCm.registerDefaultNetworkCallback(defaultCallback);
5336
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005337 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005338 mWiFiNetworkAgent.connect(true);
5339
5340 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5341 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5342
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005343 TestNetworkAgentWrapper
5344 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005345 final ArraySet<UidRange> ranges = new ArraySet<>();
5346 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005347 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5348 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005349 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
5350 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005351 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005352
Chalard Jean26400492018-04-18 20:18:38 +09005353 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5354 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5355
5356 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005357 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean26400492018-04-18 20:18:38 +09005358 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5359
Chalard Jean26400492018-04-18 20:18:38 +09005360 mCm.unregisterNetworkCallback(defaultCallback);
5361 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005362
5363 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005364 public void testVpnUnvalidated() throws Exception {
5365 final TestNetworkCallback callback = new TestNetworkCallback();
5366 mCm.registerDefaultNetworkCallback(callback);
5367
5368 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005369 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005370 mEthernetNetworkAgent.connect(true);
5371 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5372 callback.assertNoCallback();
5373
5374 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5375 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005376 final TestNetworkAgentWrapper
5377 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005378 final ArraySet<UidRange> ranges = new ArraySet<>();
5379 ranges.add(new UidRange(uid, uid));
5380 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5381 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005382 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
5383 false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005384 mMockVpn.connect();
5385
5386 // Even though the VPN is unvalidated, it becomes the default network for our app.
5387 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5388 // TODO: this looks like a spurious callback.
Chalard Jean059c4262019-09-30 17:51:12 +09005389 callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005390 callback.assertNoCallback();
5391
5392 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5393 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5394 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5395
5396 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5397 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5398 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5399
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005400 assertFalse(NetworkMonitorUtils.isValidationRequired(
5401 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005402 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005403 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005404
5405 // Pretend that the VPN network validates.
lucaslin783f2212019-10-22 18:27:33 +08005406 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005407 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5408 // Expect to see the validated capability, but no other changes, because the VPN is already
5409 // the default network for the app.
5410 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5411 callback.assertNoCallback();
5412
5413 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005414 callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005415 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5416 }
5417
5418 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005419 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005420 final int uid = Process.myUid();
5421
5422 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5423 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5424 .removeCapability(NET_CAPABILITY_NOT_VPN)
5425 .addTransportType(TRANSPORT_VPN)
5426 .build();
5427 NetworkCapabilities nc;
5428 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5429 vpnNetworkCallback.assertNoCallback();
5430
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005431 final TestNetworkAgentWrapper
5432 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005433 final ArraySet<UidRange> ranges = new ArraySet<>();
5434 ranges.add(new UidRange(uid, uid));
5435 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5436 mMockVpn.connect();
5437 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005438 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5439 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005440
5441 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5442 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5443 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5444 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5445 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5446 // For safety reasons a VPN without underlying networks is considered metered.
5447 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5448
5449 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005450 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005451 mCellNetworkAgent.connect(true);
5452
5453 mService.setUnderlyingNetworksForVpn(
5454 new Network[] { mCellNetworkAgent.getNetwork() });
5455
Chalard Jean6f4216f2019-06-05 01:40:32 +09005456 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5457 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005458 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005459 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005460
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005461 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005462 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5463 mWiFiNetworkAgent.connect(true);
5464
5465 mService.setUnderlyingNetworksForVpn(
5466 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5467
Chalard Jean6f4216f2019-06-05 01:40:32 +09005468 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5469 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005470 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005471 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005472
5473 // Don't disconnect, but note the VPN is not using wifi any more.
5474 mService.setUnderlyingNetworksForVpn(
5475 new Network[] { mCellNetworkAgent.getNetwork() });
5476
Chalard Jean6f4216f2019-06-05 01:40:32 +09005477 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5478 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005479 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005480 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005481
5482 // Use Wifi but not cell. Note the VPN is now unmetered.
5483 mService.setUnderlyingNetworksForVpn(
5484 new Network[] { mWiFiNetworkAgent.getNetwork() });
5485
Chalard Jean6f4216f2019-06-05 01:40:32 +09005486 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5487 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005488 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005489 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005490
5491 // Use both again.
5492 mService.setUnderlyingNetworksForVpn(
5493 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5494
Chalard Jean6f4216f2019-06-05 01:40:32 +09005495 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5496 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005497 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005498 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005499
Chalard Jean6b65ec72018-05-18 22:02:56 +09005500 // Disconnect cell. Receive update without even removing the dead network from the
5501 // underlying networks – it's dead anyway. Not metered any more.
5502 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005503 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5504 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005505 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005506 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005507
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005508 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005509 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005510 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5511 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005512 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005513 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005514
5515 mMockVpn.disconnect();
5516 }
junyulai4a192e22018-06-13 15:00:37 +08005517
Mike Yuf9729752018-08-17 15:22:05 +08005518 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005519 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005520 final int uid = Process.myUid();
5521
5522 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5523 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5524 .removeCapability(NET_CAPABILITY_NOT_VPN)
5525 .addTransportType(TRANSPORT_VPN)
5526 .build();
5527 NetworkCapabilities nc;
5528 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5529 vpnNetworkCallback.assertNoCallback();
5530
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005531 final TestNetworkAgentWrapper
5532 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005533 final ArraySet<UidRange> ranges = new ArraySet<>();
5534 ranges.add(new UidRange(uid, uid));
5535 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5536 mMockVpn.connect();
5537 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005538 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5539 false /* isStrictMode */);
Varun Anand4fa80e82019-02-06 10:13:38 -08005540
5541 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5542 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5543 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5544 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5545 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5546 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5547 // In case of no default network, VPN is considered metered.
5548 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5549
5550 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005551 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005552 mCellNetworkAgent.connect(true);
5553
Chalard Jean6f4216f2019-06-05 01:40:32 +09005554 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5555 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005556 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005557 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005558
5559 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005560 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005561 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5562 mWiFiNetworkAgent.connect(true);
5563
Chalard Jean6f4216f2019-06-05 01:40:32 +09005564 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5565 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005566 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005567 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005568
5569 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5570 // the capabilities.
5571 mCellNetworkAgent.disconnect();
5572
5573 // Disconnect wifi too. Now we have no default network.
5574 mWiFiNetworkAgent.disconnect();
5575
Chalard Jean6f4216f2019-06-05 01:40:32 +09005576 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5577 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005578 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005579 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005580
5581 mMockVpn.disconnect();
5582 }
5583
5584 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005585 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005586 // Returns true by default when no network is available.
5587 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005588 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005589 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5590 mWiFiNetworkAgent.connect(true);
5591 waitForIdle();
5592
5593 assertFalse(mCm.isActiveNetworkMetered());
5594 }
5595
5596 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005597 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005598 // Returns true by default when no network is available.
5599 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005600 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005601 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5602 mCellNetworkAgent.connect(true);
5603 waitForIdle();
5604
5605 assertTrue(mCm.isActiveNetworkMetered());
5606 }
5607
5608 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005609 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005610 // Returns true by default when no network is available.
5611 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005612 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005613 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5614 mCellNetworkAgent.connect(true);
5615 waitForIdle();
5616 assertTrue(mCm.isActiveNetworkMetered());
5617
5618 // Connect VPN network. By default it is using current default network (Cell).
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005619 TestNetworkAgentWrapper
5620 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005621 final ArraySet<UidRange> ranges = new ArraySet<>();
5622 final int uid = Process.myUid();
5623 ranges.add(new UidRange(uid, uid));
5624 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5625 mMockVpn.setUids(ranges);
5626 vpnNetworkAgent.connect(true);
5627 mMockVpn.connect();
5628 waitForIdle();
5629 // Ensure VPN is now the active network.
5630 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5631
5632 // Expect VPN to be metered.
5633 assertTrue(mCm.isActiveNetworkMetered());
5634
5635 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005636 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005637 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5638 mWiFiNetworkAgent.connect(true);
5639 waitForIdle();
5640 // VPN should still be the active network.
5641 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5642
5643 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5644 assertFalse(mCm.isActiveNetworkMetered());
5645
5646 // Disconnecting Cell should not affect VPN's meteredness.
5647 mCellNetworkAgent.disconnect();
5648 waitForIdle();
5649
5650 assertFalse(mCm.isActiveNetworkMetered());
5651
5652 // Disconnect WiFi; Now there is no platform default network.
5653 mWiFiNetworkAgent.disconnect();
5654 waitForIdle();
5655
5656 // VPN without any underlying networks is treated as metered.
5657 assertTrue(mCm.isActiveNetworkMetered());
5658
5659 vpnNetworkAgent.disconnect();
5660 mMockVpn.disconnect();
5661 }
5662
5663 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005664 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005665 // Returns true by default when no network is available.
5666 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005667 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005668 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5669 mCellNetworkAgent.connect(true);
5670 waitForIdle();
5671 assertTrue(mCm.isActiveNetworkMetered());
5672
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005673 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005674 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5675 mWiFiNetworkAgent.connect(true);
5676 waitForIdle();
5677 assertFalse(mCm.isActiveNetworkMetered());
5678
5679 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005680 TestNetworkAgentWrapper
5681 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005682 final ArraySet<UidRange> ranges = new ArraySet<>();
5683 final int uid = Process.myUid();
5684 ranges.add(new UidRange(uid, uid));
5685 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5686 mMockVpn.setUids(ranges);
5687 vpnNetworkAgent.connect(true);
5688 mMockVpn.connect();
5689 waitForIdle();
5690 // Ensure VPN is now the active network.
5691 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5692 // VPN is using Cell
5693 mService.setUnderlyingNetworksForVpn(
5694 new Network[] { mCellNetworkAgent.getNetwork() });
5695 waitForIdle();
5696
5697 // Expect VPN to be metered.
5698 assertTrue(mCm.isActiveNetworkMetered());
5699
5700 // VPN is now using WiFi
5701 mService.setUnderlyingNetworksForVpn(
5702 new Network[] { mWiFiNetworkAgent.getNetwork() });
5703 waitForIdle();
5704
5705 // Expect VPN to be unmetered
5706 assertFalse(mCm.isActiveNetworkMetered());
5707
5708 // VPN is using Cell | WiFi.
5709 mService.setUnderlyingNetworksForVpn(
5710 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5711 waitForIdle();
5712
5713 // Expect VPN to be metered.
5714 assertTrue(mCm.isActiveNetworkMetered());
5715
5716 // VPN is using WiFi | Cell.
5717 mService.setUnderlyingNetworksForVpn(
5718 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5719 waitForIdle();
5720
5721 // Order should not matter and VPN should still be metered.
5722 assertTrue(mCm.isActiveNetworkMetered());
5723
5724 // VPN is not using any underlying networks.
5725 mService.setUnderlyingNetworksForVpn(new Network[0]);
5726 waitForIdle();
5727
5728 // VPN without underlying networks is treated as metered.
5729 assertTrue(mCm.isActiveNetworkMetered());
5730
5731 vpnNetworkAgent.disconnect();
5732 mMockVpn.disconnect();
5733 }
5734
5735 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005736 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005737 // Returns true by default when no network is available.
5738 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005739 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005740 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5741 mWiFiNetworkAgent.connect(true);
5742 waitForIdle();
5743 assertFalse(mCm.isActiveNetworkMetered());
5744
5745 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005746 TestNetworkAgentWrapper
5747 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005748 final ArraySet<UidRange> ranges = new ArraySet<>();
5749 final int uid = Process.myUid();
5750 ranges.add(new UidRange(uid, uid));
5751 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5752 mMockVpn.setUids(ranges);
5753 vpnNetworkAgent.connect(true);
5754 mMockVpn.connectAsAlwaysMetered();
5755 waitForIdle();
5756 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5757
5758 // VPN is tracking current platform default (WiFi).
5759 mService.setUnderlyingNetworksForVpn(null);
5760 waitForIdle();
5761
5762 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5763 assertTrue(mCm.isActiveNetworkMetered());
5764
5765 // VPN explicitly declares WiFi as its underlying network.
5766 mService.setUnderlyingNetworksForVpn(
5767 new Network[] { mWiFiNetworkAgent.getNetwork() });
5768 waitForIdle();
5769
5770 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5771 assertTrue(mCm.isActiveNetworkMetered());
5772
5773 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5774 // anyways suppose to be metered.
5775 mWiFiNetworkAgent.disconnect();
5776 waitForIdle();
5777
5778 assertTrue(mCm.isActiveNetworkMetered());
5779
5780 vpnNetworkAgent.disconnect();
5781 }
5782
5783 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005784 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005785 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5786 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5787 .addTransportType(TRANSPORT_CELLULAR)
5788 .build();
5789 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5790
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005791 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005792 mCellNetworkAgent.connect(true);
5793 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5794
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005795 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08005796 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5797
5798 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005799 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005800 cellNetworkCallback.assertNoCallback();
5801
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005802 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005803 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5804
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005805 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005806 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5807
5808 // Restrict the network based on UID rule and NOT_METERED capability change.
5809 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5810 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5811 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5812 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5813 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5814 mCellNetworkAgent);
5815 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005816 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005817 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5818
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005819 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005820 cellNetworkCallback.assertNoCallback();
5821
5822 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005823 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005824 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005825 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005826 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005827 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005828 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5829 cellNetworkCallback.assertNoCallback();
5830
5831 mCm.unregisterNetworkCallback(cellNetworkCallback);
5832 }
5833
5834 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005835 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005836 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5837 mCm.registerDefaultNetworkCallback(defaultCallback);
5838
5839 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005840 setUidRulesChanged(RULE_REJECT_ALL);
5841 setUidRulesChanged(RULE_NONE);
5842 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005843 defaultCallback.assertNoCallback();
5844
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005845 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005846 mCellNetworkAgent.connect(true);
5847 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5848 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5849
5850 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005851 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08005852 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5853 mWiFiNetworkAgent.connect(true);
5854 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5855
5856 // Switch to METERED network. Restrict the use of the network.
5857 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005858 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005859 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5860
5861 // Network becomes NOT_METERED.
5862 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5863 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5864 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5865
5866 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005867 setRestrictBackgroundChanged(true);
5868 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005869 defaultCallback.assertNoCallback();
5870
5871 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005872 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005873 defaultCallback.assertNoCallback();
5874
5875 mCm.unregisterNetworkCallback(defaultCallback);
5876 }
5877
Chalard Jean143124b2019-12-03 22:13:37 +09005878 @Test
5879 public final void testLoseTrusted() throws Exception {
5880 final NetworkRequest trustedRequest = new NetworkRequest.Builder()
5881 .addCapability(NET_CAPABILITY_TRUSTED)
5882 .build();
5883 final TestNetworkCallback trustedCallback = new TestNetworkCallback();
5884 mCm.requestNetwork(trustedRequest, trustedCallback);
5885
5886 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5887 mCellNetworkAgent.connect(true);
5888 trustedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5889 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005890 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005891
5892 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5893 mWiFiNetworkAgent.connect(true);
Chalard Jean10c8d542020-02-20 07:32:12 +00005894 trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean143124b2019-12-03 22:13:37 +09005895 verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005896 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005897
5898 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
Chalard Jean143124b2019-12-03 22:13:37 +09005899 trustedCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5900 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005901 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005902
5903 mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
5904 trustedCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5905 verify(mNetworkManagementService).clearDefaultNetId();
5906
5907 mCm.unregisterNetworkCallback(trustedCallback);
5908 }
5909
Chalard Jeanb6ec0762019-12-03 16:12:33 +09005910 @Ignore // 40%+ flakiness : figure out why and re-enable.
Chalard Jean587758b2019-11-29 16:41:50 +09005911 @Test
5912 public final void testBatteryStatsNetworkType() throws Exception {
5913 final LinkProperties cellLp = new LinkProperties();
5914 cellLp.setInterfaceName("cell0");
5915 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5916 mCellNetworkAgent.connect(true);
5917 waitForIdle();
5918 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5919 TYPE_MOBILE);
5920 reset(mBatteryStatsService);
5921
5922 final LinkProperties wifiLp = new LinkProperties();
5923 wifiLp.setInterfaceName("wifi0");
5924 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
5925 mWiFiNetworkAgent.connect(true);
5926 waitForIdle();
5927 verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(),
5928 TYPE_WIFI);
5929 reset(mBatteryStatsService);
5930
Chalard Jean587758b2019-11-29 16:41:50 +09005931 mCellNetworkAgent.disconnect();
5932
5933 cellLp.setInterfaceName("wifi0");
5934 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5935 mCellNetworkAgent.connect(true);
5936 waitForIdle();
5937 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5938 TYPE_MOBILE);
5939 }
5940
junyulai4a192e22018-06-13 15:00:37 +08005941 /**
5942 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5943 */
5944 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5945 InterfaceConfiguration cfg = new InterfaceConfiguration();
5946 cfg.setHardwareAddress("11:22:33:44:55:66");
5947 cfg.setLinkAddress(la);
5948 return cfg;
5949 }
5950
5951 /**
5952 * Make expected stack link properties, copied from Nat464Xlat.
5953 */
5954 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5955 LinkAddress clatAddress = la;
5956 LinkProperties stacked = new LinkProperties();
5957 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5958 RouteInfo ipv4Default = new RouteInfo(
5959 new LinkAddress(Inet4Address.ANY, 0),
5960 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5961 stacked.addRoute(ipv4Default);
5962 stacked.addLinkAddress(clatAddress);
5963 return stacked;
5964 }
5965
5966 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005967 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08005968 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5969 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005970 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5971 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005972 final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(),
5973 MOBILE_IFNAME);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00005974 final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
5975 final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005976 final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(),
5977 CLAT_PREFIX + MOBILE_IFNAME);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005978
junyulai4a192e22018-06-13 15:00:37 +08005979 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5980 .addTransportType(TRANSPORT_CELLULAR)
5981 .addCapability(NET_CAPABILITY_INTERNET)
5982 .build();
5983 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5984 mCm.registerNetworkCallback(networkRequest, networkCallback);
5985
Lorenzo Colittid593e292019-02-19 13:21:56 +09005986 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005987 final LinkProperties cellLp = new LinkProperties();
5988 cellLp.setInterfaceName(MOBILE_IFNAME);
5989 cellLp.addLinkAddress(myIpv6);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005990 cellLp.addRoute(defaultRoute);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00005991 cellLp.addRoute(ipv6Subnet);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005992 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005993 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005994 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005995 reset(mMockNetd);
Chalard Jean587758b2019-11-29 16:41:50 +09005996 reset(mBatteryStatsService);
junyulai4a192e22018-06-13 15:00:37 +08005997
Lorenzo Colittid593e292019-02-19 13:21:56 +09005998 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005999 mCellNetworkAgent.connect(true);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09006000 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
Chalard Jean587758b2019-11-29 16:41:50 +09006001 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08006002
6003 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006004 assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute);
Luke Huanga24d5d82019-04-09 18:41:49 +08006005 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
Chalard Jean587758b2019-11-29 16:41:50 +09006006 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
6007 TYPE_MOBILE);
Luke Huanga24d5d82019-04-09 18:41:49 +08006008
junyulai4a192e22018-06-13 15:00:37 +08006009 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006010 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006011
Lorenzo Colittid593e292019-02-19 13:21:56 +09006012 // Switching default network updates TCP buffer sizes.
6013 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6014
6015 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
6016 // the NAT64 prefix was removed because one was never discovered.
6017 cellLp.addLinkAddress(myIpv4);
6018 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006019 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006020 assertRoutesAdded(cellNetId, ipv4Subnet);
Luke Huang65914772019-03-16 00:31:46 +08006021 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08006022 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006023
Chalard Jean587758b2019-11-29 16:41:50 +09006024 // Make sure BatteryStats was not told about any v4- interfaces, as none should have
6025 // come online yet.
6026 waitForIdle();
6027 verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt());
6028
Lorenzo Colittid593e292019-02-19 13:21:56 +09006029 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006030 verifyNoMoreInteractions(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006031 reset(mNetworkManagementService);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006032 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006033 reset(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006034 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6035 .thenReturn(getClatInterfaceConfig(myIpv4));
Lorenzo Colittid593e292019-02-19 13:21:56 +09006036
6037 // Remove IPv4 address. Expect prefix discovery to be started again.
6038 cellLp.removeLinkAddress(myIpv4);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006039 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006040 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08006041 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006042 assertRoutesRemoved(cellNetId, ipv4Subnet);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006043
6044 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006045 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006046 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006047 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6048 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006049 LinkProperties lpBeforeClat = networkCallback.expectCallback(
Chalard Jean059c4262019-09-30 17:51:12 +09006050 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006051 assertEquals(0, lpBeforeClat.getStackedLinks().size());
6052 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
6053 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6054
6055 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08006056 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean059c4262019-09-30 17:51:12 +09006057 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006058 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
6059 .getStackedLinks();
6060 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006061 assertRoutesAdded(cellNetId, stackedDefault);
junyulai4a192e22018-06-13 15:00:37 +08006062
6063 // Change trivial linkproperties and see if stacked link is preserved.
6064 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
6065 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006066 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006067
6068 List<LinkProperties> stackedLpsAfterChange =
6069 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
6070 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
6071 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
6072
Luke Huang65914772019-03-16 00:31:46 +08006073 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08006074 mResolverParamsParcelCaptor.capture());
6075 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6076 assertEquals(1, resolvrParams.servers.length);
6077 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08006078
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09006079 for (final LinkProperties stackedLp : stackedLpsAfterChange) {
6080 verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(),
6081 TYPE_MOBILE);
6082 }
Lorenzo Colittid86407b2020-03-18 07:52:25 +00006083 reset(mMockNetd);
Chalard Jean587758b2019-11-29 16:41:50 +09006084
Lorenzo Colittid593e292019-02-19 13:21:56 +09006085 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
6086 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08006087 cellLp.addLinkAddress(myIpv4);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006088 cellLp.addRoute(ipv4Subnet);
junyulai4a192e22018-06-13 15:00:37 +08006089 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006090 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006091 assertRoutesAdded(cellNetId, ipv4Subnet);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09006092 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08006093 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006094
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006095 // As soon as stop is called, the linkproperties lose the stacked interface.
Chalard Jean059c4262019-09-30 17:51:12 +09006096 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006097 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
6098 LinkProperties expected = new LinkProperties(cellLp);
6099 expected.setNat64Prefix(kNat64Prefix);
6100 assertEquals(expected, actualLpAfterIpv4);
6101 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006102 assertRoutesRemoved(cellNetId, stackedDefault);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006103
6104 // The interface removed callback happens but has no effect after stop is called.
6105 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6106 networkCallback.assertNoCallback();
6107
Lorenzo Colittid593e292019-02-19 13:21:56 +09006108 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006109 verifyNoMoreInteractions(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006110 reset(mNetworkManagementService);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006111 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006112 reset(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006113 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6114 .thenReturn(getClatInterfaceConfig(myIpv4));
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006115
Lorenzo Colittid593e292019-02-19 13:21:56 +09006116 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6117 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6118 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006119 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6120 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006121
6122 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006123 cellLp.removeLinkAddress(myIpv4);
6124 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6125 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6126 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006127 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006128 assertRoutesRemoved(cellNetId, ipv4Subnet); // Directly-connected routes auto-added.
Luke Huang65914772019-03-16 00:31:46 +08006129 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006130 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6131 kNat64PrefixString, 96);
Chalard Jean059c4262019-09-30 17:51:12 +09006132 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006133 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6134
6135 // Clat iface comes up. Expect stacked link to be added.
6136 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006137 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6138 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006139 assertRoutesAdded(cellNetId, stackedDefault);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006140
6141 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006142 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6143 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006144 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6145 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006146 assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
6147
6148 // Stop has no effect because clat is already stopped.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006149 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006150 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6151 (lp) -> lp.getStackedLinks().size() == 0);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006152 verifyNoMoreInteractions(mMockNetd);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006153
6154 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08006155 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006156 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006157 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08006158 mCm.unregisterNetworkCallback(networkCallback);
6159 }
Chiachang Wanga6093042018-09-28 22:42:48 +08006160
6161 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006162 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08006163 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6164 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6165 .addCapability(NET_CAPABILITY_INTERNET)
6166 .build();
6167 mCm.registerNetworkCallback(networkRequest, networkCallback);
6168
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006169 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08006170 final LinkProperties cellLp = new LinkProperties();
6171 cellLp.setInterfaceName(MOBILE_IFNAME);
6172 mCellNetworkAgent.sendLinkProperties(cellLp);
6173 reset(mNetworkManagementService);
6174 mCellNetworkAgent.connect(true);
6175 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6176 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6177 eq(ConnectivityManager.TYPE_MOBILE));
6178
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006179 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006180 final LinkProperties wifiLp = new LinkProperties();
6181 wifiLp.setInterfaceName(WIFI_IFNAME);
6182 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6183
6184 // Network switch
6185 reset(mNetworkManagementService);
6186 mWiFiNetworkAgent.connect(true);
6187 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006188 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006189 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6190 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6191 eq(ConnectivityManager.TYPE_WIFI));
6192 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6193
6194 // Disconnect wifi and switch back to cell
6195 reset(mNetworkManagementService);
6196 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006197 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006198 assertNoCallbacks(networkCallback);
6199 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6200 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6201 eq(ConnectivityManager.TYPE_MOBILE));
6202
6203 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006204 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006205 wifiLp.setInterfaceName(WIFI_IFNAME);
6206 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6207 mWiFiNetworkAgent.connect(true);
6208 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006209 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006210 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6211
6212 // Disconnect cell
6213 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006214 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006215 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006216 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006217 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6218 // sent as network being switched. Ensure rule removal for cell will not be triggered
6219 // unexpectedly before network being removed.
6220 waitForIdle();
6221 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006222 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6223 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08006224 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006225
6226 // Disconnect wifi
Chalard Jean407deb72019-11-19 16:14:30 +09006227 ConditionVariable cv = registerConnectivityBroadcast(1);
Chiachang Wanga6093042018-09-28 22:42:48 +08006228 reset(mNetworkManagementService);
6229 mWiFiNetworkAgent.disconnect();
6230 waitFor(cv);
6231 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6232
6233 // Clean up
6234 mCm.unregisterNetworkCallback(networkCallback);
6235 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006236
Chalard Jeane7b24752019-06-20 16:01:19 +09006237 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006238 String[] values = tcpBufferSizes.split(",");
6239 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6240 String wmemValues = String.join(" ", values[3], values[4], values[5]);
Chalard Jeane7b24752019-06-20 16:01:19 +09006241 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006242 reset(mMockNetd);
6243 }
6244
6245 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006246 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006247 final String testTcpBufferSizes = "1,2,3,4,5,6";
paulhu66269b32019-08-30 19:24:36 +08006248 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6249 .addTransportType(TRANSPORT_CELLULAR)
6250 .addCapability(NET_CAPABILITY_INTERNET)
6251 .build();
6252 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6253 mCm.registerNetworkCallback(networkRequest, networkCallback);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006254
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006255 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006256 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006257 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006258 mCellNetworkAgent.connect(false);
paulhu66269b32019-08-30 19:24:36 +08006259 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006260 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6261
6262 // Change link Properties should have updated tcp buffer size.
6263 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006264 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006265 mCellNetworkAgent.sendLinkProperties(lp);
Chalard Jean059c4262019-09-30 17:51:12 +09006266 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006267 verifyTcpBufferSizeChange(testTcpBufferSizes);
paulhu66269b32019-08-30 19:24:36 +08006268
6269 // Clean up.
6270 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006271 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
paulhu66269b32019-08-30 19:24:36 +08006272 networkCallback.assertNoCallback();
6273 mCm.unregisterNetworkCallback(networkCallback);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006274 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006275
6276 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006277 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006278 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006279 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006280 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6281 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6282 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6283 }
6284
6285 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006286 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006287 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006288 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006289 mWiFiNetworkAgent.connect(true);
6290 waitForIdle();
6291 assertNull(mService.getProxyForNetwork(null));
6292
6293 final LinkProperties testLinkProperties = new LinkProperties();
6294 testLinkProperties.setHttpProxy(testProxyInfo);
6295
6296 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6297 waitForIdle();
6298
6299 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6300 }
6301
6302 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006303 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006304 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6305
6306 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006307 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006308 mWiFiNetworkAgent.connect(true);
6309 waitForIdle();
6310 assertNull(mService.getProxyForNetwork(null));
6311
6312 // Set up a VPN network with a proxy
6313 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006314 final TestNetworkAgentWrapper
6315 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006316 final ArraySet<UidRange> ranges = new ArraySet<>();
6317 ranges.add(new UidRange(uid, uid));
6318 mMockVpn.setUids(ranges);
6319 LinkProperties testLinkProperties = new LinkProperties();
6320 testLinkProperties.setHttpProxy(testProxyInfo);
6321 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6322 waitForIdle();
6323
6324 // Connect to VPN with proxy
6325 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6326 vpnNetworkAgent.connect(true);
6327 mMockVpn.connect();
6328 waitForIdle();
6329
6330 // Test that the VPN network returns a proxy, and the WiFi does not.
6331 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6332 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6333 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6334
6335 // Test that the VPN network returns no proxy when it is set to null.
6336 testLinkProperties.setHttpProxy(null);
6337 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6338 waitForIdle();
6339 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6340 assertNull(mService.getProxyForNetwork(null));
6341
6342 // Set WiFi proxy and check that the vpn proxy is still null.
6343 testLinkProperties.setHttpProxy(testProxyInfo);
6344 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6345 waitForIdle();
6346 assertNull(mService.getProxyForNetwork(null));
6347
6348 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6349 // correct proxy setting.
6350 vpnNetworkAgent.disconnect();
6351 waitForIdle();
6352 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6353 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6354 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6355 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006356
6357 @Test
6358 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6359 LinkProperties lp = new LinkProperties();
6360 lp.setInterfaceName("tun0");
6361 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00006362 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006363 // The uid range needs to cover the test app so the network is visible to it.
6364 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006365 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006366
6367 // Connected VPN should have interface rules set up. There are two expected invocations,
6368 // one during VPN uid update, one during VPN LinkProperties update
6369 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6370 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6371 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6372 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6373 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6374
6375 vpnNetworkAgent.disconnect();
6376 waitForIdle();
6377
6378 // Disconnected VPN should have interface rules removed
6379 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6380 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6381 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6382 }
6383
6384 @Test
6385 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6386 LinkProperties lp = new LinkProperties();
6387 lp.setInterfaceName("tun0");
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00006388 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006389 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6390 // The uid range needs to cover the test app so the network is visible to it.
6391 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006392 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6393 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006394
6395 // Legacy VPN should not have interface rules set up
6396 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6397 }
6398
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09006399 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006400 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6401 throws Exception {
6402 LinkProperties lp = new LinkProperties();
6403 lp.setInterfaceName("tun0");
6404 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6405 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6406 // The uid range needs to cover the test app so the network is visible to it.
6407 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006408 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6409 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006410
6411 // IPv6 unreachable route should not be misinterpreted as a default route
6412 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6413 }
6414
6415 @Test
6416 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6417 LinkProperties lp = new LinkProperties();
6418 lp.setInterfaceName("tun0");
6419 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00006420 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006421 // The uid range needs to cover the test app so the network is visible to it.
6422 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006423 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006424
6425 // Connected VPN should have interface rules set up. There are two expected invocations,
6426 // one during VPN uid update, one during VPN LinkProperties update
6427 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6428 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6429 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6430 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6431
6432 reset(mMockNetd);
6433 InOrder inOrder = inOrder(mMockNetd);
6434 lp.setInterfaceName("tun1");
6435 vpnNetworkAgent.sendLinkProperties(lp);
6436 waitForIdle();
6437 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6438 // removed first, then new rules added)
6439 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6440 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6441 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6442 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6443
6444 reset(mMockNetd);
6445 lp = new LinkProperties();
6446 lp.setInterfaceName("tun1");
6447 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6448 vpnNetworkAgent.sendLinkProperties(lp);
6449 waitForIdle();
6450 // VPN not routing everything should no longer have interface filtering rules
6451 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6452 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6453
6454 reset(mMockNetd);
6455 lp = new LinkProperties();
6456 lp.setInterfaceName("tun1");
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00006457 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006458 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6459 vpnNetworkAgent.sendLinkProperties(lp);
6460 waitForIdle();
6461 // Back to routing all IPv6 traffic should have filtering rules
6462 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6463 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6464 }
6465
6466 @Test
6467 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6468 LinkProperties lp = new LinkProperties();
6469 lp.setInterfaceName("tun0");
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +00006470 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006471 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6472 // The uid range needs to cover the test app so the network is visible to it.
6473 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006474 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006475 Collections.singleton(vpnRange));
6476
6477 reset(mMockNetd);
6478 InOrder inOrder = inOrder(mMockNetd);
6479
6480 // Update to new range which is old range minus APP1, i.e. only APP2
6481 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6482 new UidRange(vpnRange.start, APP1_UID - 1),
6483 new UidRange(APP1_UID + 1, vpnRange.stop)));
6484 vpnNetworkAgent.setUids(newRanges);
6485 waitForIdle();
6486
6487 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6488 // Verify old rules are removed before new rules are added
6489 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6490 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6491 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6492 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6493 }
6494
Valentin Iftimec86ebba2019-09-24 13:32:13 +02006495 @Test
6496 public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
6497 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6498
6499 LinkProperties wifiLp = new LinkProperties();
6500 wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
6501 wifiLp.setWakeOnLanSupported(false);
6502
6503 // Default network switch should update ifaces.
6504 mWiFiNetworkAgent.connect(false);
6505 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6506 waitForIdle();
6507
6508 // ConnectivityService should have changed the WakeOnLanSupported to true
6509 wifiLp.setWakeOnLanSupported(true);
6510 assertEquals(wifiLp, mService.getActiveLinkProperties());
6511 }
6512
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006513 private void setupLocationPermissions(
6514 int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
6515 final ApplicationInfo applicationInfo = new ApplicationInfo();
6516 applicationInfo.targetSdkVersion = targetSdk;
6517 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
6518 .thenReturn(applicationInfo);
6519
6520 when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
6521
6522 if (op != null) {
6523 when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
6524 .thenReturn(AppOpsManager.MODE_ALLOWED);
6525 }
6526
6527 if (perm != null) {
6528 mServiceContext.setPermission(perm, PERMISSION_GRANTED);
6529 }
6530 }
6531
6532 private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
6533 final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
6534
6535 return mService
6536 .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
6537 .getOwnerUid();
6538 }
6539
Qingxi Li7cf06622020-01-17 17:54:27 -08006540 @Test
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006541 public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
6542 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6543 Manifest.permission.ACCESS_FINE_LOCATION);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006544
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006545 final int myUid = Process.myUid();
6546 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6547 }
Qingxi Li7cf06622020-01-17 17:54:27 -08006548
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006549 @Test
6550 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception {
6551 setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
6552 Manifest.permission.ACCESS_COARSE_LOCATION);
6553
6554 final int myUid = Process.myUid();
6555 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6556 }
6557
6558 @Test
6559 public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception {
6560 // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
6561 setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
6562 Manifest.permission.ACCESS_FINE_LOCATION);
6563
6564 final int myUid = Process.myUid();
6565 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6566 }
6567
6568 @Test
6569 public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception {
6570 // Test that even with fine location permission, not being the owner leads to sanitization.
6571 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6572 Manifest.permission.ACCESS_FINE_LOCATION);
6573
6574 final int myUid = Process.myUid();
6575 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
6576 }
6577
6578 @Test
6579 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception {
6580 // Test that not having fine location permission leads to sanitization.
6581 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
6582 Manifest.permission.ACCESS_COARSE_LOCATION);
6583
6584 // Test that without the location permission, the owner field is sanitized.
6585 final int myUid = Process.myUid();
6586 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6587 }
6588
6589 @Test
6590 public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception {
6591 setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
6592
6593 // Test that without the location permission, the owner field is sanitized.
6594 final int myUid = Process.myUid();
6595 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
Qingxi Li7cf06622020-01-17 17:54:27 -08006596 }
6597
Benedict Wong5d50ce82020-01-20 22:14:59 -08006598 private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
6599 throws Exception {
6600 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6601 establishVpn(new LinkProperties(), vpnOwnerUid, vpnRange);
6602 mMockVpn.setVpnType(vpnType);
6603
6604 final VpnInfo vpnInfo = new VpnInfo();
6605 vpnInfo.ownerUid = vpnOwnerUid;
6606 mMockVpn.setVpnInfo(vpnInfo);
6607 }
6608
6609 private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
6610 throws Exception {
6611 setupConnectionOwnerUid(vpnOwnerUid, vpnType);
6612
6613 // Test as VPN app
6614 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6615 mServiceContext.setPermission(
6616 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
6617 }
6618
6619 private ConnectionInfo getTestConnectionInfo() throws Exception {
6620 return new ConnectionInfo(
6621 IPPROTO_TCP,
6622 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
6623 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
6624 }
6625
6626 @Test
6627 public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
6628 final int myUid = Process.myUid();
6629 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
6630
6631 try {
6632 mService.getConnectionOwnerUid(getTestConnectionInfo());
6633 fail("Expected SecurityException for non-VpnService app");
6634 } catch (SecurityException expected) {
6635 }
6636 }
6637
6638 @Test
6639 public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
6640 final int myUid = Process.myUid();
6641 setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
6642
6643 try {
6644 mService.getConnectionOwnerUid(getTestConnectionInfo());
6645 fail("Expected SecurityException for non-VpnService app");
6646 } catch (SecurityException expected) {
6647 }
6648 }
6649
6650 @Test
6651 public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
6652 final int myUid = Process.myUid();
6653 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
6654
6655 // TODO: Test the returned UID
6656 mService.getConnectionOwnerUid(getTestConnectionInfo());
6657 }
6658
6659 @Test
6660 public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
6661 final int myUid = Process.myUid();
6662 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
6663 mServiceContext.setPermission(
6664 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6665
6666 // TODO: Test the returned UID
6667 mService.getConnectionOwnerUid(getTestConnectionInfo());
6668 }
6669
6670 @Test
6671 public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
6672 throws Exception {
6673 final int myUid = Process.myUid();
6674 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
6675 mServiceContext.setPermission(
6676 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
6677
6678 // TODO: Test the returned UID
6679 mService.getConnectionOwnerUid(getTestConnectionInfo());
6680 }
6681
Qingxi Li7cf06622020-01-17 17:54:27 -08006682 private TestNetworkAgentWrapper establishVpn(
6683 LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006684 final TestNetworkAgentWrapper
6685 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
Qingxi Li7cf06622020-01-17 17:54:27 -08006686 vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006687 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6688 mMockVpn.connect();
6689 mMockVpn.setUids(vpnRange);
6690 vpnNetworkAgent.connect(true);
6691 waitForIdle();
6692 return vpnNetworkAgent;
6693 }
6694
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006695 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6696 final PackageInfo packageInfo = new PackageInfo();
paulhu86e23eb2019-11-05 18:05:05 +08006697 if (hasSystemPermission) {
6698 packageInfo.requestedPermissions = new String[] {
6699 CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
6700 packageInfo.requestedPermissionsFlags = new int[] {
6701 REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
6702 } else {
6703 packageInfo.requestedPermissions = new String[0];
6704 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006705 packageInfo.applicationInfo = new ApplicationInfo();
6706 packageInfo.applicationInfo.privateFlags = 0;
6707 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6708 UserHandle.getAppId(uid));
6709 return packageInfo;
6710 }
Cody Kesting63e4e002019-12-18 10:57:50 -08006711
6712 @Test
6713 public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
6714 final NetworkRequest request =
6715 new NetworkRequest(
6716 new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
6717 try {
6718 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006719 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006720 fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
6721 } catch (IllegalArgumentException expected) {
6722 }
6723 }
6724
Lorenzo Colittid86407b2020-03-18 07:52:25 +00006725 private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
6726 assertEquals(route.getDestination().toString(), parcel.destination);
6727 assertEquals(route.getInterface(), parcel.ifName);
6728 assertEquals(route.getMtu(), parcel.mtu);
6729
6730 switch (route.getType()) {
6731 case RouteInfo.RTN_UNICAST:
6732 if (route.hasGateway()) {
6733 assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
6734 } else {
6735 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
6736 }
6737 break;
6738 case RouteInfo.RTN_UNREACHABLE:
6739 assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
6740 break;
6741 case RouteInfo.RTN_THROW:
6742 assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
6743 break;
6744 default:
6745 assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
6746 break;
6747 }
6748 }
6749
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006750 private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
Lorenzo Colittid86407b2020-03-18 07:52:25 +00006751 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
6752 verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006753 for (int i = 0; i < routes.length; i++) {
Lorenzo Colittid86407b2020-03-18 07:52:25 +00006754 assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006755 }
6756 }
6757
6758 private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
Lorenzo Colittid86407b2020-03-18 07:52:25 +00006759 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
6760 verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
6761 captor.capture());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006762 for (int i = 0; i < routes.length; i++) {
Lorenzo Colittid86407b2020-03-18 07:52:25 +00006763 assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006764 }
6765 }
6766
Cody Kesting63e4e002019-12-18 10:57:50 -08006767 @Test
6768 public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
6769 final NetworkRequest wifiRequest =
6770 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
Cody Kesting63e4e002019-12-18 10:57:50 -08006771 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6772
6773 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006774 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006775
Cody Kestinge330fcd2020-01-15 16:31:08 -08006776 // Block until all other events are done processing.
6777 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6778
6779 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
6780 verify(mConnectivityDiagnosticsCallback).asBinder();
Cody Kesting4600fa52020-03-05 10:46:02 -08006781 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
Cody Kesting63e4e002019-12-18 10:57:50 -08006782
6783 mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
6784 verify(mIBinder, timeout(TIMEOUT_MS))
6785 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
Cody Kesting4600fa52020-03-05 10:46:02 -08006786 assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
Cody Kesting63e4e002019-12-18 10:57:50 -08006787 verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
6788 }
6789
6790 @Test
6791 public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
6792 final NetworkRequest wifiRequest =
6793 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
6794 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6795
6796 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006797 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006798
Cody Kestinge330fcd2020-01-15 16:31:08 -08006799 // Block until all other events are done processing.
6800 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6801
6802 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
Cody Kesting63e4e002019-12-18 10:57:50 -08006803 verify(mConnectivityDiagnosticsCallback).asBinder();
Cody Kesting4600fa52020-03-05 10:46:02 -08006804 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
Cody Kesting63e4e002019-12-18 10:57:50 -08006805
6806 // Register the same callback again
6807 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006808 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006809
6810 // Block until all other events are done processing.
6811 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6812
Cody Kesting4600fa52020-03-05 10:46:02 -08006813 assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
Cody Kesting63e4e002019-12-18 10:57:50 -08006814 }
Cody Kestinga75e26b2020-01-05 14:06:39 -08006815
6816 @Test
6817 public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
6818 final NetworkAgentInfo naiWithoutUid =
6819 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006820 null, null, null, null, null, new NetworkCapabilities(), 0,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006821 mServiceContext, null, null, mService, null, null, null, 0);
6822
6823 mServiceContext.setPermission(
6824 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6825 assertTrue(
6826 "NetworkStack permission not applied",
6827 mService.checkConnectivityDiagnosticsPermissions(
6828 Process.myPid(), Process.myUid(), naiWithoutUid,
6829 mContext.getOpPackageName()));
6830 }
6831
6832 @Test
Automerger Merge Workera5333b92020-03-16 15:48:50 +00006833 public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
6834 final NetworkAgentInfo naiWithoutUid =
6835 new NetworkAgentInfo(
6836 null, null, null, null, null, new NetworkCapabilities(), 0,
6837 mServiceContext, null, null, mService, null, null, null, 0);
6838
6839 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6840
Automerger Merge Worker69fad4c2020-03-16 20:37:44 +00006841 assertFalse(
6842 "Mismatched uid/package name should not pass the location permission check",
6843 mService.checkConnectivityDiagnosticsPermissions(
6844 Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
6845 mContext.getOpPackageName()));
Automerger Merge Workera5333b92020-03-16 15:48:50 +00006846 }
6847
6848 @Test
Cody Kestinga75e26b2020-01-05 14:06:39 -08006849 public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
6850 final NetworkAgentInfo naiWithoutUid =
6851 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006852 null, null, null, null, null, new NetworkCapabilities(), 0,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006853 mServiceContext, null, null, mService, null, null, null, 0);
6854
6855 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6856
6857 assertFalse(
6858 "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics",
6859 mService.checkConnectivityDiagnosticsPermissions(
6860 Process.myPid(), Process.myUid(), naiWithoutUid,
6861 mContext.getOpPackageName()));
6862 }
6863
6864 @Test
6865 public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
Cody Kesting3096b662020-03-18 21:11:29 +00006866 final Network network = new Network(NET_ID);
Cody Kestinga75e26b2020-01-05 14:06:39 -08006867 final NetworkAgentInfo naiWithoutUid =
6868 new NetworkAgentInfo(
Cody Kesting3096b662020-03-18 21:11:29 +00006869 null, null, network, null, null, new NetworkCapabilities(), 0,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006870 mServiceContext, null, null, mService, null, null, null, 0);
6871
6872 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6873 Manifest.permission.ACCESS_FINE_LOCATION);
6874 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6875
6876 // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be
6877 // active
6878 final VpnInfo info = new VpnInfo();
6879 info.ownerUid = Process.myUid();
6880 info.vpnIface = "interface";
6881 mMockVpn.setVpnInfo(info);
Cody Kesting3096b662020-03-18 21:11:29 +00006882 mMockVpn.overrideUnderlyingNetworks(new Network[] {network});
Cody Kestinga75e26b2020-01-05 14:06:39 -08006883 assertTrue(
6884 "Active VPN permission not applied",
6885 mService.checkConnectivityDiagnosticsPermissions(
6886 Process.myPid(), Process.myUid(), naiWithoutUid,
6887 mContext.getOpPackageName()));
Cody Kesting3096b662020-03-18 21:11:29 +00006888
6889 mMockVpn.overrideUnderlyingNetworks(null);
6890 assertFalse(
6891 "VPN shouldn't receive callback on non-underlying network",
6892 mService.checkConnectivityDiagnosticsPermissions(
6893 Process.myPid(), Process.myUid(), naiWithoutUid,
6894 mContext.getOpPackageName()));
Cody Kestinga75e26b2020-01-05 14:06:39 -08006895 }
6896
6897 @Test
6898 public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
6899 final NetworkCapabilities nc = new NetworkCapabilities();
Cody Kestingf7ac9962020-03-16 18:15:28 -07006900 nc.setAdministratorUids(new int[] {Process.myUid()});
Cody Kestinga75e26b2020-01-05 14:06:39 -08006901 final NetworkAgentInfo naiWithUid =
6902 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006903 null, null, null, null, null, nc, 0, mServiceContext, null, null,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006904 mService, null, null, null, 0);
6905
6906 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6907 Manifest.permission.ACCESS_FINE_LOCATION);
6908 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6909
6910 // Disconnect mock vpn so the uid check on NetworkAgentInfo is tested
6911 mMockVpn.disconnect();
6912 assertTrue(
6913 "NetworkCapabilities administrator uid permission not applied",
6914 mService.checkConnectivityDiagnosticsPermissions(
6915 Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
6916 }
6917
6918 @Test
6919 public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
6920 final NetworkCapabilities nc = new NetworkCapabilities();
6921 nc.setOwnerUid(Process.myUid());
Cody Kestingf7ac9962020-03-16 18:15:28 -07006922 nc.setAdministratorUids(new int[] {Process.myUid()});
Cody Kestinga75e26b2020-01-05 14:06:39 -08006923 final NetworkAgentInfo naiWithUid =
6924 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006925 null, null, null, null, null, nc, 0, mServiceContext, null, null,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006926 mService, null, null, null, 0);
6927
6928 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6929 Manifest.permission.ACCESS_FINE_LOCATION);
6930 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6931
6932 // Use wrong pid and uid
6933 assertFalse(
6934 "Permissions allowed when they shouldn't be granted",
6935 mService.checkConnectivityDiagnosticsPermissions(
6936 Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
6937 mContext.getOpPackageName()));
6938 }
6939
Cody Kesting560eb262020-02-12 14:50:58 -08006940 @Test
6941 public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
6942 throws Exception {
6943 // Set up the Network, which leads to a ConnectivityReport being cached for the network.
6944 final TestNetworkCallback callback = new TestNetworkCallback();
6945 mCm.registerDefaultNetworkCallback(callback);
6946 final LinkProperties linkProperties = new LinkProperties();
6947 linkProperties.setInterfaceName(INTERFACE_NAME);
6948 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
6949 mCellNetworkAgent.connect(true);
6950 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6951 callback.assertNoCallback();
6952
6953 final NetworkRequest request = new NetworkRequest.Builder().build();
6954 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6955
6956 mServiceContext.setPermission(
6957 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6958
6959 mService.registerConnectivityDiagnosticsCallback(
6960 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
6961
6962 // Block until all other events are done processing.
6963 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6964
6965 verify(mConnectivityDiagnosticsCallback)
6966 .onConnectivityReportAvailable(argThat(report -> {
6967 return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
6968 && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
6969 }));
6970 }
6971
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006972 private void setUpConnectivityDiagnosticsCallback() throws Exception {
Cody Kestinga75e26b2020-01-05 14:06:39 -08006973 final NetworkRequest request = new NetworkRequest.Builder().build();
6974 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6975
6976 mServiceContext.setPermission(
6977 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6978
6979 mService.registerConnectivityDiagnosticsCallback(
6980 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
6981
6982 // Block until all other events are done processing.
6983 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6984
6985 // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
6986 final TestNetworkCallback callback = new TestNetworkCallback();
6987 mCm.registerDefaultNetworkCallback(callback);
6988 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6989 mCellNetworkAgent.connect(true);
6990 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6991 callback.assertNoCallback();
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006992 }
6993
6994 @Test
Cody Kesting9347e332020-03-05 15:19:48 -08006995 public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable()
6996 throws Exception {
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006997 setUpConnectivityDiagnosticsCallback();
Cody Kestinga75e26b2020-01-05 14:06:39 -08006998
Cody Kestinge330fcd2020-01-15 16:31:08 -08006999 // Block until all other events are done processing.
7000 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7001
7002 // Verify onConnectivityReport fired
Cody Kesting9347e332020-03-05 15:19:48 -08007003 verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable(
Cody Kestinga3b71c42020-02-11 10:03:26 -08007004 argThat(report -> {
7005 final NetworkCapabilities nc = report.getNetworkCapabilities();
7006 return nc.getUids() == null
Cody Kestingf7ac9962020-03-16 18:15:28 -07007007 && nc.getAdministratorUids().length == 0
Cody Kestinga3b71c42020-02-11 10:03:26 -08007008 && nc.getOwnerUid() == Process.INVALID_UID;
7009 }));
Cody Kestinga75e26b2020-01-05 14:06:39 -08007010 }
Cody Kesting4f49f142020-01-06 16:55:35 -08007011
7012 @Test
7013 public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007014 setUpConnectivityDiagnosticsCallback();
Cody Kesting4f49f142020-01-06 16:55:35 -08007015
7016 // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
7017 // cellular network agent
7018 mCellNetworkAgent.notifyDataStallSuspected();
7019
Cody Kestinge330fcd2020-01-15 16:31:08 -08007020 // Block until all other events are done processing.
7021 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7022
7023 // Verify onDataStallSuspected fired
Cody Kestinga3b71c42020-02-11 10:03:26 -08007024 verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(
7025 argThat(report -> {
7026 final NetworkCapabilities nc = report.getNetworkCapabilities();
7027 return nc.getUids() == null
Cody Kestingf7ac9962020-03-16 18:15:28 -07007028 && nc.getAdministratorUids().length == 0
Cody Kestinga3b71c42020-02-11 10:03:26 -08007029 && nc.getOwnerUid() == Process.INVALID_UID;
7030 }));
Cody Kesting4f49f142020-01-06 16:55:35 -08007031 }
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007032
7033 @Test
7034 public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
7035 setUpConnectivityDiagnosticsCallback();
7036
7037 final Network n = mCellNetworkAgent.getNetwork();
7038 final boolean hasConnectivity = true;
7039 mService.reportNetworkConnectivity(n, hasConnectivity);
7040
Cody Kestinge330fcd2020-01-15 16:31:08 -08007041 // Block until all other events are done processing.
7042 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7043
7044 // Verify onNetworkConnectivityReported fired
7045 verify(mConnectivityDiagnosticsCallback)
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007046 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
7047
7048 final boolean noConnectivity = false;
7049 mService.reportNetworkConnectivity(n, noConnectivity);
7050
Cody Kestinge330fcd2020-01-15 16:31:08 -08007051 // Block until all other events are done processing.
7052 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
7053
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007054 // Wait for onNetworkConnectivityReported to fire
Cody Kestinge330fcd2020-01-15 16:31:08 -08007055 verify(mConnectivityDiagnosticsCallback)
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08007056 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
7057 }
Lorenzo Colittid86407b2020-03-18 07:52:25 +00007058
7059 @Test
7060 public void testRouteAddDeleteUpdate() throws Exception {
7061 final NetworkRequest request = new NetworkRequest.Builder().build();
7062 final TestNetworkCallback networkCallback = new TestNetworkCallback();
7063 mCm.registerNetworkCallback(request, networkCallback);
7064 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
7065 reset(mMockNetd);
7066 mCellNetworkAgent.connect(false);
7067 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
7068 final int netId = mCellNetworkAgent.getNetwork().netId;
7069
7070 final String iface = "rmnet_data0";
7071 final InetAddress gateway = InetAddress.getByName("fe80::5678");
7072 RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
7073 RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
7074 RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
7075 RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
7076 RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
7077 1280 /* mtu */);
7078
7079 // Send LinkProperties and check that we ask netd to add routes.
7080 LinkProperties lp = new LinkProperties();
7081 lp.setInterfaceName(iface);
7082 lp.addRoute(direct);
7083 lp.addRoute(rio1);
7084 lp.addRoute(defaultRoute);
7085 mCellNetworkAgent.sendLinkProperties(lp);
7086 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3);
7087
7088 assertRoutesAdded(netId, direct, rio1, defaultRoute);
7089 reset(mMockNetd);
7090
7091 // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
7092 assertTrue(lp.getRoutes().contains(defaultRoute));
7093 lp.removeRoute(rio1);
7094 lp.addRoute(rio2);
7095 lp.addRoute(defaultWithMtu);
7096 // Ensure adding the same route with a different MTU replaces the previous route.
7097 assertFalse(lp.getRoutes().contains(defaultRoute));
7098 assertTrue(lp.getRoutes().contains(defaultWithMtu));
7099
7100 mCellNetworkAgent.sendLinkProperties(lp);
7101 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
7102 x -> x.getRoutes().contains(rio2));
7103
7104 assertRoutesRemoved(netId, rio1);
7105 assertRoutesAdded(netId, rio2);
7106
7107 ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
7108 verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
7109 assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
7110
7111
7112 mCm.unregisterNetworkCallback(networkCallback);
7113 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07007114}