blob: 4236b9d43e90976113d6f72e1fbb0d5b1344a555 [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;
Cody Kestinga75e26b2020-01-05 14:06:39 -080026import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
Cody Kesting4f49f142020-01-06 16:55:35 -080027import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090028import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
Erik Klinef851d6d2015-04-20 16:03:48 +090029import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Chalard Jean9ca13772019-11-15 12:08:36 +090030import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
31import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
32import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090033import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070034import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
35import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
36import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090037import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070038import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090039import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
40import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Chalard Jean9ca13772019-11-15 12:08:36 +090041import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070042import static android.net.ConnectivityManager.TYPE_WIFI;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080043import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
44import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
45import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
46import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
lucaslin783f2212019-10-22 18:27:33 +080047import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080048import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
49import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060050import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
52import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
53import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
54import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
55import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
57import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
58import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
59import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
60import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
61import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090062import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060063import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080064import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060065import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
66import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
67import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
68import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
69import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
70import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
71import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
72import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090073import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060074import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
75import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080076import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
77import static android.net.NetworkPolicyManager.RULE_NONE;
78import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
79import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000080import static android.net.RouteInfo.RTN_UNREACHABLE;
Benedict Wong5d50ce82020-01-20 22:14:59 -080081import static android.system.OsConstants.IPPROTO_TCP;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060082
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090083import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090084import static com.android.testutils.ConcurrentUtilsKt.await;
85import static com.android.testutils.ConcurrentUtilsKt.durationOf;
Chalard Jeane7b24752019-06-20 16:01:19 +090086import static com.android.testutils.ExceptionUtils.ignoreExceptions;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090087import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
88import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
89import static com.android.testutils.MiscAssertsKt.assertEmpty;
90import static com.android.testutils.MiscAssertsKt.assertLength;
91import static com.android.testutils.MiscAssertsKt.assertRunsInAtMost;
92import static com.android.testutils.MiscAssertsKt.assertThrows;
93
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090094import static org.junit.Assert.assertEquals;
95import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080096import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090097import static org.junit.Assert.assertNotNull;
98import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060099import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900100import static org.junit.Assert.fail;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900101import static org.mockito.ArgumentMatchers.anyLong;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900102import static org.mockito.ArgumentMatchers.anyString;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000103import static org.mockito.ArgumentMatchers.eq;
Chalard Jean587758b2019-11-29 16:41:50 +0900104import static org.mockito.ArgumentMatchers.startsWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900105import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +0900106import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600107import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900108import static org.mockito.Mockito.doAnswer;
109import static org.mockito.Mockito.doNothing;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900110import static org.mockito.Mockito.doReturn;
Roshan Piuse38acab2020-01-16 12:17:17 -0800111import static org.mockito.Mockito.doThrow;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000112import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -0800113import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600114import static org.mockito.Mockito.never;
115import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900116import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900117import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +0900118import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600119import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -0700120import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900121import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700122
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900123import android.Manifest;
junyulai7c469172019-01-16 20:23:34 +0800124import android.annotation.NonNull;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900125import android.app.AlarmManager;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800126import android.app.AppOpsManager;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900127import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400128import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400129import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900130import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900131import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700132import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400133import android.content.Intent;
134import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000135import android.content.pm.ApplicationInfo;
136import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100137import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000138import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900139import android.content.res.Resources;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800140import android.location.LocationManager;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900141import android.net.CaptivePortalData;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800142import android.net.ConnectionInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400143import android.net.ConnectivityManager;
144import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900145import android.net.ConnectivityManager.PacketKeepalive;
146import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900147import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900148import android.net.ConnectivityThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800149import android.net.IConnectivityDiagnosticsCallback;
Luke Huang65914772019-03-16 00:31:46 +0800150import android.net.IDnsResolver;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900151import android.net.IIpConnectivityMetrics;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800152import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900153import android.net.INetworkMonitor;
154import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800155import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700156import android.net.INetworkPolicyManager;
157import android.net.INetworkStatsService;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800158import android.net.InetAddresses;
junyulai4a192e22018-06-13 15:00:37 +0800159import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900160import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800161import android.net.IpSecManager;
162import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900163import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700164import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700165import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400166import android.net.Network;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400167import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700168import android.net.NetworkFactory;
Chalard Jean9ca13772019-11-15 12:08:36 +0900169import android.net.NetworkInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400170import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700171import android.net.NetworkSpecifier;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900172import android.net.NetworkStack;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900173import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800174import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100175import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000176import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800177import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700178import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800179import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900180import android.net.UidRange;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900181import android.net.Uri;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800182import android.net.VpnManager;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900183import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900184import android.net.shared.NetworkMonitorUtils;
185import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900186import android.net.util.MultinetworkPolicyTracker;
Chalard Jean751bb3f2019-06-19 23:29:58 +0900187import android.os.BadParcelableException;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100188import android.os.Binder;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800189import android.os.Build;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900190import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400191import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700192import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700193import android.os.HandlerThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800194import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700195import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900196import android.os.Looper;
Etan Cohena7434272017-04-03 12:17:51 -0700197import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800198import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700199import android.os.Parcelable;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800200import android.os.PersistableBundle;
Robin Leed2baf792016-03-24 12:07:00 +0000201import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800202import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900203import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900204import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000205import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900206import android.provider.Settings;
Benedict Wongb570e862020-01-17 19:33:55 -0800207import android.security.KeyStore;
junyulai0c666972019-03-04 22:45:36 +0800208import android.system.Os;
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
junyulai4a192e22018-06-13 15:00:37 +0800311 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700312 private static final String MOBILE_IFNAME = "test_rmnet_data0";
313 private static final String WIFI_IFNAME = "test_wlan0";
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200314 private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
Roshan Piuse38acab2020-01-16 12:17:17 -0800315 private static final String TEST_PACKAGE_NAME = "com.android.test.package";
Luke Huang65914772019-03-16 00:31:46 +0800316 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700317
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900318 private MockContext mServiceContext;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900319 private HandlerThread mCsHandlerThread;
320 private ConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900321 private WrappedConnectivityManager mCm;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900322 private TestNetworkAgentWrapper mWiFiNetworkAgent;
323 private TestNetworkAgentWrapper mCellNetworkAgent;
324 private TestNetworkAgentWrapper mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900325 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900326 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800327 private INetworkPolicyListener mPolicyListener;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900328 private WrappedMultinetworkPolicyTracker mPolicyTracker;
329 private HandlerThread mAlarmManagerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700330
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900331 @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
Hugo Benichi64901e52017-10-19 14:42:40 +0900332 @Mock IpConnectivityMetrics.Logger mMetricsService;
333 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900334 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600335 @Mock INetworkStatsService mStatsService;
Chalard Jean587758b2019-11-29 16:41:50 +0900336 @Mock IBatteryStats mBatteryStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800337 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800338 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800339 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900340 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100341 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000342 @Mock UserManager mUserManager;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900343 @Mock NotificationManager mNotificationManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900344 @Mock AlarmManager mAlarmManager;
Cody Kesting63e4e002019-12-18 10:57:50 -0800345 @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
346 @Mock IBinder mIBinder;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800347 @Mock LocationManager mLocationManager;
348 @Mock AppOpsManager mAppOpsManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900349
waynema13516842019-03-12 18:13:49 +0800350 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
351 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900352
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900353 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
354 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
355 // reflect the state of our test ConnectivityService.
356 private class WrappedConnectivityManager extends ConnectivityManager {
357 private Network mFakeBoundNetwork;
358
359 public synchronized boolean bindProcessToNetwork(Network network) {
360 mFakeBoundNetwork = network;
361 return true;
362 }
363
364 public synchronized Network getBoundNetworkForProcess() {
365 return mFakeBoundNetwork;
366 }
367
368 public WrappedConnectivityManager(Context context, ConnectivityService service) {
369 super(context, service);
370 }
371 }
372
Paul Jensend7b6ca92015-05-13 14:05:12 -0400373 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900374 private final MockContentResolver mContentResolver;
Chalard Jean9ca13772019-11-15 12:08:36 +0900375 // Contains all registered receivers since this object was created. Useful to clear
376 // them when needed, as BroadcastInterceptingContext does not provide this facility.
377 private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>();
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900378
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900379 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900380 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900381 // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
382 private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900383
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900384 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400385 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900386
387 mResources = spy(base.getResources());
388 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
389 thenReturn(new String[] {
390 "wifi,1,1,1,-1,true",
391 "mobile,0,0,0,-1,true",
392 "mobile_mms,2,0,2,60000,true",
Chalard Jean9ca13772019-11-15 12:08:36 +0900393 "mobile_supl,3,0,2,60000,true",
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900394 });
395
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200396 when(mResources.getStringArray(
397 com.android.internal.R.array.config_wakeonlan_supported_interfaces))
398 .thenReturn(new String[]{
399 WIFI_WOL_IFNAME,
400 });
401
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900402 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900403 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400404 }
405
406 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900407 public void startActivityAsUser(Intent intent, UserHandle handle) {
408 mStartedActivities.offer(intent);
409 }
410
Chalard Jeanf30d1e12019-06-27 08:24:51 +0000411 public Intent expectStartActivityIntent(int timeoutMs) {
412 Intent intent = null;
413 try {
414 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
415 } catch (InterruptedException e) {}
416 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
417 return intent;
418 }
419
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900420 public void expectNoStartActivityIntent(int timeoutMs) {
421 try {
422 assertNull("Received unexpected Intent to start activity",
423 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
424 } catch (InterruptedException e) {}
425 }
426
427 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900428 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900429 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900430 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900431 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000432 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900433 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800434 if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
435 if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400436 return super.getSystemService(name);
437 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900438
439 @Override
440 public ContentResolver getContentResolver() {
441 return mContentResolver;
442 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900443
444 @Override
445 public Resources getResources() {
446 return mResources;
447 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100448
449 @Override
450 public PackageManager getPackageManager() {
451 return mPackageManager;
452 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900453
Benedict Wong5d50ce82020-01-20 22:14:59 -0800454 private int checkMockedPermission(String permission, Supplier<Integer> ifAbsent) {
455 final Integer granted = mMockedPermissions.get(permission);
456 return granted != null ? granted : ifAbsent.get();
457 }
458
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900459 @Override
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900460 public int checkPermission(String permission, int pid, int uid) {
Benedict Wong5d50ce82020-01-20 22:14:59 -0800461 return checkMockedPermission(
462 permission, () -> super.checkPermission(permission, pid, uid));
463 }
464
465 @Override
466 public int checkCallingOrSelfPermission(String permission) {
467 return checkMockedPermission(
468 permission, () -> super.checkCallingOrSelfPermission(permission));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900469 }
470
471 @Override
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900472 public void enforceCallingOrSelfPermission(String permission, String message) {
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900473 final Integer granted = mMockedPermissions.get(permission);
474 if (granted == null) {
475 super.enforceCallingOrSelfPermission(permission, message);
476 return;
477 }
478
479 if (!granted.equals(PERMISSION_GRANTED)) {
480 throw new SecurityException("[Test] permission denied: " + permission);
481 }
482 }
483
484 /**
485 * Mock checks for the specified permission, and have them behave as per {@code granted}.
486 *
487 * <p>Passing null reverts to default behavior, which does a real permission check on the
488 * test package.
489 * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
490 * {@link PackageManager#PERMISSION_DENIED}.
491 */
492 public void setPermission(String permission, Integer granted) {
493 mMockedPermissions.put(permission, granted);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900494 }
Chalard Jean9ca13772019-11-15 12:08:36 +0900495
496 @Override
497 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
498 mRegisteredReceivers.add(receiver);
499 return super.registerReceiver(receiver, filter);
500 }
501
502 public void clearRegisteredReceivers() {
503 // super.unregisterReceiver is a no-op for receivers that are not registered (because
504 // they haven't been registered or because they have already been unregistered).
505 // For the same reason, don't bother clearing mRegisteredReceivers.
506 for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv);
507 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900508 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400509
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900510 private void waitForIdle() {
511 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
512 waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
513 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
514 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
515 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
516 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Hugo Benichibb91c572017-05-22 10:44:02 +0900517 }
518
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900519 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900520 if (agent == null) {
521 return;
522 }
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900523 agent.waitForIdle(timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900524 }
525
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900526 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +0900527 public void testWaitForIdle() throws Exception {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900528 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
529
530 // Tests that waitForIdle returns immediately if the service is already idle.
531 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900532 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900533 }
534
535 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900536 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900537 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900538 mWiFiNetworkAgent.connect(false);
539 waitFor(cv);
540 Network n = mWiFiNetworkAgent.getNetwork();
541 assertNotNull(n);
542
543 // Tests that calling waitForIdle waits for messages to be processed.
544 for (int i = 0; i < attempts; i++) {
545 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900546 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900547 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
548 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900549 }
550
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900551 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
552 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800553 @Ignore
Chalard Jeane7b24752019-06-20 16:01:19 +0900554 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900555 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900556 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900557 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Hugo Benichi5d540d12016-10-17 15:54:51 +0900558 mWiFiNetworkAgent.connect(false);
559 waitFor(cv);
560 Network n = mWiFiNetworkAgent.getNetwork();
561 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900562
563 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900564 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900565 for (int i = 0; i < attempts; i++) {
566 mWiFiNetworkAgent.setSignalStrength(i);
567 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
568 // We hit a race condition, as expected. Pass the test.
569 return;
570 }
571 }
572
573 // No race? There is a bug in this test.
574 fail("expected race condition at least once in " + attempts + " attempts");
575 }
576
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900577 private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800578 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
579 | NETWORK_VALIDATION_PROBE_HTTP
580 | NETWORK_VALIDATION_PROBE_HTTPS;
581 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
582 | NETWORK_VALIDATION_RESULT_VALID;
583 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
584 | NETWORK_VALIDATION_PROBE_FALLBACK
585 | NETWORK_VALIDATION_RESULT_PARTIAL;
586 private static final int VALIDATION_RESULT_INVALID = 0;
587
Cody Kesting4f49f142020-01-06 16:55:35 -0800588 private static final long DATA_STALL_TIMESTAMP = 10L;
589 private static final int DATA_STALL_DETECTION_METHOD = 1;
590
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900591 private INetworkMonitor mNetworkMonitor;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900592 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800593 private int mNmValidationResult = VALIDATION_RESULT_BASE;
lucaslin783f2212019-10-22 18:27:33 +0800594 private int mProbesCompleted;
595 private int mProbesSucceeded;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900596 private String mNmValidationRedirectUrl = null;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800597 private PersistableBundle mValidationExtras = PersistableBundle.EMPTY;
Cody Kesting4f49f142020-01-06 16:55:35 -0800598 private PersistableBundle mDataStallExtras = PersistableBundle.EMPTY;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900599 private boolean mNmProvNotificationRequested = false;
600
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900601 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
602 // Contains the redirectUrl from networkStatus(). Before reading, wait for
603 // mNetworkStatusReceived.
604 private String mRedirectUrl;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900605
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900606 TestNetworkAgentWrapper(int transport) throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100607 this(transport, new LinkProperties());
608 }
609
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900610 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
611 throws Exception {
612 super(transport, linkProperties, mServiceContext);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900613
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900614 // Waits for the NetworkAgent to be registered, which includes the creation of the
615 // NetworkMonitor.
616 waitForIdle(TIMEOUT_MS);
Chalard Jean3da8e0f2019-09-20 17:19:31 +0900617 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
618 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900619 }
620
621 @Override
622 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
623 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900624 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900625
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900626 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900627 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900628 return null;
629 };
630
Chalard Jeane7b24752019-06-20 16:01:19 +0900631 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
632 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900633
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900634 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900635 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
636 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
637 doNothing().when(mNetworkStack).makeNetworkMonitor(
638 nmNetworkCaptor.capture(),
639 any() /* name */,
640 nmCbCaptor.capture());
641
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900642 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400643 @Override
644 public void networkStatus(int status, String redirectUrl) {
645 mRedirectUrl = redirectUrl;
646 mNetworkStatusReceived.open();
647 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400648 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900649
Chalard Jean29c6e0c2020-01-16 17:13:26 +0900650 assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900651 mNmCallbacks = nmCbCaptor.getValue();
652
Chalard Jeane7b24752019-06-20 16:01:19 +0900653 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900654
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900655 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900656 }
657
Chalard Jeane7b24752019-06-20 16:01:19 +0900658 private void onValidationRequested() throws Exception {
659 if (mNmProvNotificationRequested
660 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
661 mNmCallbacks.hideProvisioningNotification();
662 mNmProvNotificationRequested = false;
663 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900664
lucaslin783f2212019-10-22 18:27:33 +0800665 mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
Cody Kestinga75e26b2020-01-05 14:06:39 -0800666 mNmCallbacks.notifyNetworkTestedWithExtras(
667 mNmValidationResult, mNmValidationRedirectUrl, TIMESTAMP, mValidationExtras);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900668
Chalard Jeane7b24752019-06-20 16:01:19 +0900669 if (mNmValidationRedirectUrl != null) {
670 mNmCallbacks.showProvisioningNotification(
Roshan Piuse38acab2020-01-16 12:17:17 -0800671 "test_provisioning_notif_action", TEST_PACKAGE_NAME);
Chalard Jeane7b24752019-06-20 16:01:19 +0900672 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900673 }
Paul Jensen3d911462015-06-12 06:40:24 -0400674 }
675
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900676 /**
677 * Connect without adding any internet capability.
678 */
Paul Jensene0988542015-06-25 15:30:08 -0400679 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900680 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400681 }
682
Paul Jensend7b6ca92015-05-13 14:05:12 -0400683 /**
Paul Jensene0988542015-06-25 15:30:08 -0400684 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400685 * @param validated Indicate if network should pretend to be validated.
686 */
687 public void connect(boolean validated) {
lucaslin783f2212019-10-22 18:27:33 +0800688 connect(validated, true, false /* isStrictMode */);
Hugo Benichi16f0a942017-06-20 14:07:59 +0900689 }
690
691 /**
692 * Transition this NetworkAgent to CONNECTED state.
693 * @param validated Indicate if network should pretend to be validated.
694 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
695 */
lucaslin783f2212019-10-22 18:27:33 +0800696 public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900697 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400698
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900699 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400700 final ConditionVariable validatedCv = new ConditionVariable();
701 if (validated) {
lucaslin783f2212019-10-22 18:27:33 +0800702 setNetworkValid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400703 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900704 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900705 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400706 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900707 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400708 public void onCapabilitiesChanged(Network network,
709 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400710 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900711 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400712 validatedCv.open();
713 }
714 }
715 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400716 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400717 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900718 if (hasInternet) {
719 addCapability(NET_CAPABILITY_INTERNET);
720 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400721
Paul Jensene0988542015-06-25 15:30:08 -0400722 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400723
724 if (validated) {
725 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400726 waitFor(validatedCv);
lucaslin783f2212019-10-22 18:27:33 +0800727 setNetworkInvalid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400728 }
729
730 if (callback != null) mCm.unregisterNetworkCallback(callback);
731 }
732
lucaslin783f2212019-10-22 18:27:33 +0800733 public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
734 setNetworkPortal(redirectUrl, isStrictMode);
735 connect(false, true /* hasInternet */, isStrictMode);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400736 }
737
lucasline252a742019-03-12 13:08:03 +0800738 public void connectWithPartialConnectivity() {
739 setNetworkPartial();
740 connect(false);
741 }
742
lucaslin783f2212019-10-22 18:27:33 +0800743 public void connectWithPartialValidConnectivity(boolean isStrictMode) {
744 setNetworkPartialValid(isStrictMode);
745 connect(false, true /* hasInternet */, isStrictMode);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900746 }
747
lucaslin783f2212019-10-22 18:27:33 +0800748 void setNetworkValid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900749 mNmValidationResult = VALIDATION_RESULT_VALID;
750 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800751 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP;
752 if (isStrictMode) {
753 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
754 }
755 // The probesCompleted equals to probesSucceeded for the case of valid network, so put
756 // the same value into two different parameter of the method.
757 setProbesStatus(probesSucceeded, probesSucceeded);
Erik Kline1d3db322017-02-28 16:20:20 +0900758 }
759
lucaslin783f2212019-10-22 18:27:33 +0800760 void setNetworkInvalid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900761 mNmValidationResult = VALIDATION_RESULT_INVALID;
762 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800763 int probesCompleted = VALIDATION_RESULT_BASE;
764 int probesSucceeded = VALIDATION_RESULT_INVALID;
765 // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
766 // tried to validate the private DNS but failed.
767 if (isStrictMode) {
768 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
769 probesSucceeded = probesCompleted;
770 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
771 }
772 setProbesStatus(probesCompleted, probesSucceeded);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900773 }
774
lucaslin783f2212019-10-22 18:27:33 +0800775 void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
776 setNetworkInvalid(isStrictMode);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900777 mNmValidationRedirectUrl = redirectUrl;
lucaslin783f2212019-10-22 18:27:33 +0800778 // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
779 // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
780 int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
781 int probesSucceeded = VALIDATION_RESULT_INVALID;
782 if (isStrictMode) {
783 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
784 }
785 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400786 }
787
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900788 void setNetworkPartial() {
789 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
790 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800791 int probesCompleted = VALIDATION_RESULT_BASE;
792 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
793 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400794 }
Paul Jensene0988542015-06-25 15:30:08 -0400795
lucaslin783f2212019-10-22 18:27:33 +0800796 void setNetworkPartialValid(boolean isStrictMode) {
797 setNetworkPartial();
798 mNmValidationResult |= VALIDATION_RESULT_VALID;
799 int probesCompleted = VALIDATION_RESULT_BASE;
800 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
801 // Suppose the partial network cannot pass the private DNS validation as well, so only
802 // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
803 if (isStrictMode) {
804 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
805 }
806 setProbesStatus(probesCompleted, probesSucceeded);
807 }
808
809 void setProbesStatus(int probesCompleted, int probesSucceeded) {
810 mProbesCompleted = probesCompleted;
811 mProbesSucceeded = probesSucceeded;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900812 }
Paul Jensen232437312016-04-06 09:51:26 -0400813
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +0900814 void notifyCaptivePortalDataChanged(CaptivePortalData data) {
815 try {
816 mNmCallbacks.notifyCaptivePortalDataChanged(data);
817 } catch (RemoteException e) {
818 throw new AssertionError("This cannot happen", e);
819 }
820 }
821
Paul Jensen232437312016-04-06 09:51:26 -0400822 public String waitForRedirectUrl() {
823 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
824 return mRedirectUrl;
825 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900826
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900827 public void expectDisconnected() {
828 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900829 }
830
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900831 public void expectPreventReconnectReceived() {
832 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900833 }
Cody Kesting4f49f142020-01-06 16:55:35 -0800834
835 void notifyDataStallSuspected() throws Exception {
836 mNmCallbacks.notifyDataStallSuspected(
837 DATA_STALL_TIMESTAMP, DATA_STALL_DETECTION_METHOD, mDataStallExtras);
838 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400839 }
840
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900841 /**
842 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
843 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900844 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900845 * expectRemoveRequests.
846 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700847 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400848 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
849 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400850 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700851
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900852 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900853 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
854 // once, then cause some other thread to add or remove requests, then call
855 // waitForRequests().
856 // It is not possible to wait for both add and remove requests. When adding, the queue
857 // contains the expected score. When removing, the value is unused, all matters is the
858 // number of objects in the queue.
859 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900860
861 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900862 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900863 private boolean mExpectingAdditions;
864
Etan Cohenddb720a2019-01-08 12:09:18 -0800865 // Used to collect the networks requests managed by this factory. This is a duplicate of
866 // the internal information stored in the NetworkFactory (which is private).
867 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
868
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700869 public MockNetworkFactory(Looper looper, Context context, String logTag,
870 NetworkCapabilities filter) {
871 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900872 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700873 }
874
875 public int getMyRequestCount() {
876 return getRequestCount();
877 }
878
879 protected void startNetwork() {
880 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400881 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700882 }
883
884 protected void stopNetwork() {
885 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400886 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700887 }
888
889 public boolean getMyStartRequested() {
890 return mNetworkStarted.get();
891 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400892
893 public ConditionVariable getNetworkStartedCV() {
894 mNetworkStartedCV.close();
895 return mNetworkStartedCV;
896 }
897
898 public ConditionVariable getNetworkStoppedCV() {
899 mNetworkStoppedCV.close();
900 return mNetworkStoppedCV;
901 }
902
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900903 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900904 protected void handleAddRequest(NetworkRequest request, int score,
905 int factorySerialNumber) {
906 synchronized (mExpectations) {
907 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900908
Chalard Jean05ab6812018-05-02 21:14:54 +0900909 assertNotNull("Added more requests than expected (" + request + " score : "
910 + score + ")", expectedScore);
911 // If we're expecting anything, we must be expecting additions.
912 if (!mExpectingAdditions) {
913 fail("Can't add requests while expecting requests to be removed");
914 }
915 if (expectedScore != score) {
916 fail("Expected score was " + expectedScore + " but actual was " + score
917 + " in added request");
918 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900919
Chalard Jean05ab6812018-05-02 21:14:54 +0900920 // Add the request.
921 mNetworkRequests.put(request.requestId, request);
922 super.handleAddRequest(request, score, factorySerialNumber);
923 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900924 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400925 }
926
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900927 @Override
928 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900929 synchronized (mExpectations) {
930 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900931
Chalard Jean05ab6812018-05-02 21:14:54 +0900932 assertTrue("Removed more requests than expected", expectedScore != null);
933 // If we're expecting anything, we must be expecting removals.
934 if (mExpectingAdditions) {
935 fail("Can't remove requests while expecting requests to be added");
936 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900937
Chalard Jean05ab6812018-05-02 21:14:54 +0900938 // Remove the request.
939 mNetworkRequests.remove(request.requestId);
940 super.handleRemoveRequest(request);
941 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900942 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400943 }
944
Etan Cohenddb720a2019-01-08 12:09:18 -0800945 // Trigger releasing the request as unfulfillable
946 public void triggerUnfulfillable(NetworkRequest r) {
947 super.releaseRequestAsUnfulfillableByAnyFactory(r);
948 }
949
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900950 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900951 if (mExpectations.size() != 0) {
952 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900953 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400954 }
955
Chalard Jean05ab6812018-05-02 21:14:54 +0900956 // Expects that requests with the specified scores will be added.
957 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900958 assertNoExpectations();
959 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900960 for (int score : scores) {
961 mExpectations.add(score);
962 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400963 }
964
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900965 // Expects that count requests will be removed.
966 public void expectRemoveRequests(final int count) {
967 assertNoExpectations();
968 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900969 for (int i = 0; i < count; ++i) {
970 mExpectations.add(0); // For removals the score is ignored so any value will do.
971 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900972 }
973
974 // Waits for the expected request additions or removals to happen within a timeout.
975 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900976 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
977 synchronized (mExpectations) {
978 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
979 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
980 }
981 }
982 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900983 final String msg = count + " requests still not " +
984 (mExpectingAdditions ? "added" : "removed") +
985 " after " + TIMEOUT_MS + " ms";
986 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900987 }
988
Etan Cohenddb720a2019-01-08 12:09:18 -0800989 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
990 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900991 waitForRequests();
992 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800993 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400994 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700995 }
996
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900997 private static Looper startHandlerThreadAndReturnLooper() {
998 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
999 handlerThread.start();
1000 return handlerThread.getLooper();
1001 }
1002
1003 private class MockVpn extends Vpn {
1004 // TODO : the interactions between this mock and the mock network agent are too
1005 // hard to get right at this moment, because it's unclear in which case which
1006 // target needs to get a method call or both, and in what order. It's because
1007 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
1008 // parent class of MockVpn agent wants that responsibility.
1009 // That being said inside the test it should be possible to make the interactions
1010 // harder to get wrong with precise speccing, judicious comments, helper methods
1011 // and a few sprinkled assertions.
1012
1013 private boolean mConnected = false;
1014 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1015 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001016 private TestNetworkAgentWrapper mMockNetworkAgent;
Benedict Wong5d50ce82020-01-20 22:14:59 -08001017 private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001018
Cody Kestinga75e26b2020-01-05 14:06:39 -08001019 private VpnInfo mVpnInfo;
1020
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001021 public MockVpn(int userId) {
1022 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
Benedict Wongb570e862020-01-17 19:33:55 -08001023 userId, mock(KeyStore.class));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001024 }
1025
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001026 public void setNetworkAgent(TestNetworkAgentWrapper agent) {
1027 agent.waitForIdle(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001028 mMockNetworkAgent = agent;
1029 mNetworkAgent = agent.getNetworkAgent();
1030 mNetworkCapabilities.set(agent.getNetworkCapabilities());
1031 }
1032
1033 public void setUids(Set<UidRange> uids) {
1034 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -08001035 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001036 }
1037
Benedict Wong5d50ce82020-01-20 22:14:59 -08001038 public void setVpnType(int vpnType) {
1039 mVpnType = vpnType;
1040 }
1041
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001042 @Override
1043 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -08001044 if (mMockNetworkAgent == null) {
1045 return NETID_UNSET;
1046 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001047 return mMockNetworkAgent.getNetwork().netId;
1048 }
1049
1050 @Override
1051 public boolean appliesToUid(int uid) {
1052 return mConnected; // Trickery to simplify testing.
1053 }
1054
1055 @Override
1056 protected boolean isCallerEstablishedOwnerLocked() {
1057 return mConnected; // Similar trickery
1058 }
1059
Benedict Wong5d50ce82020-01-20 22:14:59 -08001060 @Override
1061 public int getActiveAppVpnType() {
1062 return mVpnType;
1063 }
1064
Varun Anandc51b06d2019-02-25 17:22:02 -08001065 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001066 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1067 mConnected = true;
1068 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -08001069 mConfig.isMetered = isAlwaysMetered;
1070 }
1071
1072 public void connectAsAlwaysMetered() {
1073 connect(true /* isAlwaysMetered */);
1074 }
1075
1076 public void connect() {
1077 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001078 }
1079
1080 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001081 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1082 if (!mConnected) return null;
1083 super.updateCapabilities(defaultNetwork);
1084 // Because super.updateCapabilities will update the capabilities of the agent but
1085 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001086 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -08001087 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001088 }
1089
1090 private void copyCapabilitiesToNetworkAgent() {
1091 if (null != mMockNetworkAgent) {
1092 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1093 false /* sendToConnectivityService */);
1094 }
1095 }
1096
1097 public void disconnect() {
1098 mConnected = false;
1099 mConfig = null;
1100 }
Cody Kestinga75e26b2020-01-05 14:06:39 -08001101
1102 @Override
1103 public synchronized VpnInfo getVpnInfo() {
1104 if (mVpnInfo != null) return mVpnInfo;
1105
1106 return super.getVpnInfo();
1107 }
1108
1109 private void setVpnInfo(VpnInfo vpnInfo) {
1110 mVpnInfo = vpnInfo;
1111 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001112 }
1113
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001114 private void mockVpn(int uid) {
1115 synchronized (mService.mVpns) {
1116 int userId = UserHandle.getUserId(uid);
1117 mMockVpn = new MockVpn(userId);
1118 // This has no effect unless the VPN is actually connected, because things like
1119 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1120 // netId, and check if that network is actually connected.
1121 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001122 }
1123 }
1124
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001125 private void setUidRulesChanged(int uidRules) throws RemoteException {
1126 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1127 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001128
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001129 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
1130 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1131 }
1132
1133 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1134 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1135 }
1136
1137 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1138 volatile boolean mConfigRestrictsAvoidBadWifi;
1139 volatile int mConfigMeteredMultipathPreference;
1140
1141 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001142 super(c, h, r);
1143 }
1144
1145 @Override
1146 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001147 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +09001148 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001149
1150 @Override
1151 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001152 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +08001153 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001154 }
1155
Paul Jensen3d911462015-06-12 06:40:24 -04001156 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001157 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1158 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001159 */
1160 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001161 if (conditionVariable.block(TIMEOUT_MS)) {
1162 return;
1163 }
1164 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001165 }
1166
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001167 private static final int VPN_USER = 0;
1168 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1169 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1170 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1171
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001172 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001173 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001174 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001175
Hugo Benichi64901e52017-10-19 14:42:40 +09001176 MockitoAnnotations.initMocks(this);
1177 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1178
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001179 when(mUserManager.getUsers(eq(true))).thenReturn(
1180 Arrays.asList(new UserInfo[] {
1181 new UserInfo(VPN_USER, "", 0),
1182 }));
Qingxi Li9c5d8b92020-01-08 12:51:49 -08001183 final ApplicationInfo applicationInfo = new ApplicationInfo();
1184 applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1185 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
1186 .thenReturn(applicationInfo);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001187
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001188 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1189 // http://b/25897652 .
1190 if (Looper.myLooper() == null) {
1191 Looper.prepare();
1192 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001193 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001194
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001195 FakeSettingsProvider.clearSettingsProvider();
1196 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1197 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001198 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1199 LocalServices.addService(
1200 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001201
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001202 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1203 mAlarmManagerThread.start();
1204 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1205
1206 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1207 final ConnectivityService.Dependencies deps = makeDependencies();
1208 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001209 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001210 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001211 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001212 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001213 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001214 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001215 deps);
1216 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1217 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001218
Mike Yuf9729752018-08-17 15:22:05 +08001219 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1220 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1221 verify(mNpm).registerListener(policyListenerCaptor.capture());
1222 mPolicyListener = policyListenerCaptor.getValue();
1223
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001224 // Create local CM before sending system ready so that we can answer
1225 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001226 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001227 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001228 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001229 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001230
1231 // Ensure that the default setting for Captive Portals is used for most tests
1232 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001233 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001234 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001235 }
1236
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001237 private ConnectivityService.Dependencies makeDependencies() {
1238 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1239 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1240 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1241
1242 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1243 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1244 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
1245 doReturn(mNetworkStack).when(deps).getNetworkStack();
1246 doReturn(systemProperties).when(deps).getSystemProperties();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001247 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1248 doReturn(mMetricsService).when(deps).getMetricsLogger();
1249 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1250 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
Chalard Jean587758b2019-11-29 16:41:50 +09001251 doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001252 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1253 doAnswer(inv -> {
1254 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1255 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1256 return mPolicyTracker;
1257 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1258
1259 return deps;
1260 }
1261
1262 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1263 doAnswer(inv -> {
1264 final long when = inv.getArgument(1);
1265 final WakeupMessage wakeupMsg = inv.getArgument(3);
1266 final Handler handler = inv.getArgument(4);
1267
1268 long delayMs = when - SystemClock.elapsedRealtime();
1269 if (delayMs < 0) delayMs = 0;
1270 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1271 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1272 + "ms into the future: " + delayMs);
1273 }
1274 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1275 delayMs);
1276
1277 return null;
1278 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1279 any(WakeupMessage.class), any());
1280
1281 doAnswer(inv -> {
1282 final WakeupMessage wakeupMsg = inv.getArgument(0);
1283 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1284 return null;
1285 }).when(am).cancel(any(WakeupMessage.class));
1286 }
1287
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001288 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001289 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001290 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001291 if (mCellNetworkAgent != null) {
1292 mCellNetworkAgent.disconnect();
1293 mCellNetworkAgent = null;
1294 }
1295 if (mWiFiNetworkAgent != null) {
1296 mWiFiNetworkAgent.disconnect();
1297 mWiFiNetworkAgent = null;
1298 }
1299 if (mEthernetNetworkAgent != null) {
1300 mEthernetNetworkAgent.disconnect();
1301 mEthernetNetworkAgent = null;
1302 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001303 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001304
1305 mCsHandlerThread.quitSafely();
1306 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001307 }
1308
Rubin Xu9e64dc02019-04-23 18:04:14 +01001309 private void mockDefaultPackages() throws Exception {
1310 final String testPackageName = mContext.getPackageName();
1311 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1312 testPackageName, PackageManager.GET_PERMISSIONS);
1313 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1314 new String[] {testPackageName});
1315 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1316 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1317
1318 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1319 Arrays.asList(new PackageInfo[] {
1320 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1321 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1322 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1323 }));
1324 }
1325
Paul Jensend7b6ca92015-05-13 14:05:12 -04001326 private void verifyActiveNetwork(int transport) {
1327 // Test getActiveNetworkInfo()
1328 assertNotNull(mCm.getActiveNetworkInfo());
1329 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1330 // Test getActiveNetwork()
1331 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001332 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001333 if (!NetworkCapabilities.isValidTransport(transport)) {
1334 throw new IllegalStateException("Unknown transport " + transport);
1335 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001336 switch (transport) {
1337 case TRANSPORT_WIFI:
1338 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1339 break;
1340 case TRANSPORT_CELLULAR:
1341 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1342 break;
1343 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001344 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001345 }
1346 // Test getNetworkInfo(Network)
1347 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001348 assertEquals(transportToLegacyType(transport),
1349 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001350 // Test getNetworkCapabilities(Network)
1351 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1352 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1353 }
1354
1355 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001356 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001357 // Test getActiveNetworkInfo()
1358 assertNull(mCm.getActiveNetworkInfo());
1359 // Test getActiveNetwork()
1360 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001361 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001362 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001363 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001364 }
1365
1366 /**
1367 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1368 * broadcasts are received.
1369 */
Chalard Jean407deb72019-11-19 16:14:30 +09001370 private ConditionVariable registerConnectivityBroadcast(final int count) {
1371 return registerConnectivityBroadcastThat(count, intent -> true);
Chalard Jean9ca13772019-11-15 12:08:36 +09001372 }
1373
Chalard Jean407deb72019-11-19 16:14:30 +09001374 private ConditionVariable registerConnectivityBroadcastThat(final int count,
Chalard Jean9ca13772019-11-15 12:08:36 +09001375 @NonNull final Predicate<Intent> filter) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001376 final ConditionVariable cv = new ConditionVariable();
Chalard Jean9ca13772019-11-15 12:08:36 +09001377 final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
1378 intentFilter.addAction(CONNECTIVITY_ACTION_SUPL);
1379 final BroadcastReceiver receiver = new BroadcastReceiver() {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001380 private int remaining = count;
1381 public void onReceive(Context context, Intent intent) {
Chalard Jean9ca13772019-11-15 12:08:36 +09001382 if (!filter.test(intent)) return;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001383 if (--remaining == 0) {
1384 cv.open();
1385 mServiceContext.unregisterReceiver(this);
1386 }
1387 }
Chalard Jean9ca13772019-11-15 12:08:36 +09001388 };
1389 mServiceContext.registerReceiver(receiver, intentFilter);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001390 return cv;
1391 }
1392
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001393 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001394 public void testNetworkTypes() {
1395 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1396 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1397 // will fail. Failing here is much easier to debug.
1398 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1399 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001400 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1401 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1402
1403 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1404 // mocks, this assert exercises the ConnectivityService code path that ensures that
1405 // TYPE_ETHERNET is supported if the ethernet service is running.
1406 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001407 }
1408
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001409 @Test
Chalard Jean9ca13772019-11-15 12:08:36 +09001410 public void testNetworkFeature() throws Exception {
1411 // Connect the cell agent and wait for the connected broadcast.
1412 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1413 mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
Chalard Jean407deb72019-11-19 16:14:30 +09001414 final ConditionVariable cv1 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001415 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE);
1416 mCellNetworkAgent.connect(true);
1417 waitFor(cv1);
1418
1419 // Build legacy request for SUPL.
1420 final NetworkCapabilities legacyCaps = new NetworkCapabilities();
1421 legacyCaps.addTransportType(TRANSPORT_CELLULAR);
1422 legacyCaps.addCapability(NET_CAPABILITY_SUPL);
1423 final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
1424 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
1425
1426 // Send request and check that the legacy broadcast for SUPL is sent correctly.
1427 final TestNetworkCallback callback = new TestNetworkCallback();
Chalard Jean407deb72019-11-19 16:14:30 +09001428 final ConditionVariable cv2 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001429 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1430 mCm.requestNetwork(legacyRequest, callback);
1431 callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1432 waitFor(cv2);
1433
1434 // File another request, withdraw it and make sure no broadcast is sent
Chalard Jean407deb72019-11-19 16:14:30 +09001435 final ConditionVariable cv3 = registerConnectivityBroadcast(1);
Chalard Jean9ca13772019-11-15 12:08:36 +09001436 final TestNetworkCallback callback2 = new TestNetworkCallback();
1437 mCm.requestNetwork(legacyRequest, callback2);
1438 callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1439 mCm.unregisterNetworkCallback(callback2);
1440 assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent
1441 // As the broadcast did not fire, the receiver was not unregistered. Do this now.
1442 mServiceContext.clearRegisteredReceivers();
1443
1444 // Withdraw the request and check that the broadcast for disconnection is sent.
Chalard Jean407deb72019-11-19 16:14:30 +09001445 final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent ->
Chalard Jean9ca13772019-11-15 12:08:36 +09001446 !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected()
1447 && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1448 mCm.unregisterNetworkCallback(callback);
1449 waitFor(cv4);
1450
1451 // Re-file the request and expect the connected broadcast again
Chalard Jean407deb72019-11-19 16:14:30 +09001452 final ConditionVariable cv5 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001453 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1454 final TestNetworkCallback callback3 = new TestNetworkCallback();
1455 mCm.requestNetwork(legacyRequest, callback3);
1456 callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1457 waitFor(cv5);
1458
1459 // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one
1460 // for mobile. Use a small hack to check that both have been sent, but the order is
1461 // not contractual.
1462 final AtomicBoolean vanillaAction = new AtomicBoolean(false);
1463 final AtomicBoolean suplAction = new AtomicBoolean(false);
Chalard Jean407deb72019-11-19 16:14:30 +09001464 final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> {
Chalard Jean9ca13772019-11-15 12:08:36 +09001465 if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
1466 vanillaAction.set(true);
1467 } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) {
1468 suplAction.set(true);
1469 }
1470 return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
1471 });
1472 mCellNetworkAgent.disconnect();
1473 waitFor(cv6);
1474 assertTrue(vanillaAction.get());
1475 assertTrue(suplAction.get());
1476 }
1477
1478 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001479 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001480 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001481 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1482 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001483 assertNull(mCm.getActiveNetworkInfo());
1484 assertNull(mCm.getActiveNetwork());
1485 // Test bringing up validated cellular.
Chalard Jean407deb72019-11-19 16:14:30 +09001486 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001487 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001488 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001489 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001490 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001491 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1492 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1493 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1494 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1495 // Test bringing up validated WiFi.
Chalard Jean407deb72019-11-19 16:14:30 +09001496 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001497 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001498 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001499 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001500 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001501 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1502 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1503 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1504 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1505 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001506 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001507 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001508 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001509 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001510 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001511 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1512 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001513 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001514 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001515 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001516 verifyNoNetwork();
1517 }
1518
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001519 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001520 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1521 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001522 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001523 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001524 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001525 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001526 verifyActiveNetwork(TRANSPORT_WIFI);
1527 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001528 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001529 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001530 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001531 verifyActiveNetwork(TRANSPORT_WIFI);
1532 // Test cellular disconnect.
1533 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001534 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001535 verifyActiveNetwork(TRANSPORT_WIFI);
1536 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001537 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001538 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001539 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001540 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001541 verifyActiveNetwork(TRANSPORT_CELLULAR);
1542 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001543 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001544 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001545 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001546 verifyActiveNetwork(TRANSPORT_WIFI);
1547 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001548 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001549 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001550 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001551 verifyNoNetwork();
1552 }
1553
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001554 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001555 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1556 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001557 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001558 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001559 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001560 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001561 verifyActiveNetwork(TRANSPORT_CELLULAR);
1562 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001563 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001564 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001565 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001566 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001567 verifyActiveNetwork(TRANSPORT_WIFI);
1568 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001569 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001570 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001571 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001572 verifyActiveNetwork(TRANSPORT_CELLULAR);
1573 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001574 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001575 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001576 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001577 verifyNoNetwork();
1578 }
1579
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001580 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001581 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001582 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001583 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001584 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001585 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001586 waitFor(cv);
1587 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001588 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001589 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001590 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001591 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001592 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001593 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001594 waitFor(cv);
1595 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001596 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1597 NET_CAPABILITY_VALIDATED));
1598 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001599 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001600 mCellNetworkAgent.disconnect();
1601 waitFor(cv);
1602 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001603 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001604 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001605 NET_CAPABILITY_VALIDATED));
1606 }
1607
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001608 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001609 public void testCellularOutscoresWeakWifi() throws Exception {
1610 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001611 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001612 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001613 mCellNetworkAgent.connect(true);
1614 waitFor(cv);
1615 verifyActiveNetwork(TRANSPORT_CELLULAR);
1616 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001617 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001618 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001619 mWiFiNetworkAgent.connect(true);
1620 waitFor(cv);
1621 verifyActiveNetwork(TRANSPORT_WIFI);
1622 // Test WiFi getting really weak.
Chalard Jean407deb72019-11-19 16:14:30 +09001623 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001624 mWiFiNetworkAgent.adjustScore(-11);
1625 waitFor(cv);
1626 verifyActiveNetwork(TRANSPORT_CELLULAR);
1627 // Test WiFi restoring signal strength.
Chalard Jean407deb72019-11-19 16:14:30 +09001628 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001629 mWiFiNetworkAgent.adjustScore(11);
1630 waitFor(cv);
1631 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001632 }
1633
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001634 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001635 public void testReapingNetwork() throws Exception {
1636 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1637 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001638 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001639 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001640 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001641 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1642 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001643 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001644 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001645 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001646 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001647 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001648 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001649 mWiFiNetworkAgent.connect(true);
1650 waitFor(cv);
1651 verifyActiveNetwork(TRANSPORT_WIFI);
1652 // Test bringing up unvalidated cellular.
1653 // Expect it to be torn down because it could never be the highest scoring network
1654 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001655 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001656 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001657 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001658 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001659 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001660 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001661 }
1662
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001663 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001664 public void testCellularFallback() throws Exception {
1665 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001666 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001667 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001668 mCellNetworkAgent.connect(true);
1669 waitFor(cv);
1670 verifyActiveNetwork(TRANSPORT_CELLULAR);
1671 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001672 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001673 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001674 mWiFiNetworkAgent.connect(true);
1675 waitFor(cv);
1676 verifyActiveNetwork(TRANSPORT_WIFI);
1677 // Reevaluate WiFi (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001678 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001679 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1680 NET_CAPABILITY_VALIDATED));
1681 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1682 // Should quickly fall back to Cellular.
1683 waitFor(cv);
1684 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1685 NET_CAPABILITY_VALIDATED));
1686 verifyActiveNetwork(TRANSPORT_CELLULAR);
1687 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001688 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001689 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1690 NET_CAPABILITY_VALIDATED));
1691 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1692 // Should quickly fall back to WiFi.
1693 waitFor(cv);
1694 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1695 NET_CAPABILITY_VALIDATED));
1696 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1697 NET_CAPABILITY_VALIDATED));
1698 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001699 }
1700
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001701 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001702 public void testWiFiFallback() throws Exception {
1703 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001704 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001705 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001706 mWiFiNetworkAgent.connect(false);
1707 waitFor(cv);
1708 verifyActiveNetwork(TRANSPORT_WIFI);
1709 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001710 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001711 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001712 mCellNetworkAgent.connect(true);
1713 waitFor(cv);
1714 verifyActiveNetwork(TRANSPORT_CELLULAR);
1715 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001716 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001717 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1718 NET_CAPABILITY_VALIDATED));
1719 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1720 // Should quickly fall back to WiFi.
1721 waitFor(cv);
1722 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1723 NET_CAPABILITY_VALIDATED));
1724 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001725 }
1726
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001727 @Test
1728 public void testRequiresValidation() {
1729 assertTrue(NetworkMonitorUtils.isValidationRequired(
1730 mCm.getDefaultRequest().networkCapabilities));
1731 }
1732
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001733 /**
1734 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1735 * this class receives, by calling expectCallback() exactly once each time a callback is
1736 * received. assertNoCallback may be called at any time.
1737 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001738 private class TestNetworkCallback extends TestableNetworkCallback {
Chalard Jeanb299b842019-09-27 17:13:14 +09001739 TestNetworkCallback() {
1740 super(TEST_CALLBACK_TIMEOUT_MS);
1741 }
1742
Chalard Jean6f4216f2019-06-05 01:40:32 +09001743 @Override
1744 public void assertNoCallback() {
1745 // TODO: better support this use case in TestableNetworkCallback
1746 waitForIdle();
1747 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001748 }
Paul Jensen3d911462015-06-12 06:40:24 -04001749
Erik Klineacdd6392016-07-07 16:50:58 +09001750 @Override
Chalard Jean059c4262019-09-30 17:51:12 +09001751 public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
Chalard Jean6f4216f2019-06-05 01:40:32 +09001752 final long timeoutMs) {
1753 final T callback = super.expectCallback(type, n, timeoutMs);
Chalard Jean059c4262019-09-30 17:51:12 +09001754 if (callback instanceof CallbackEntry.Losing) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09001755 // TODO : move this to the specific test(s) needing this rather than here.
Chalard Jean059c4262019-09-30 17:51:12 +09001756 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001757 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001758 String msg = String.format(
1759 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001760 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001761 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001762 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001763 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001764 }
1765 }
1766
1767 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1768 // only be declared in a static or top level type".
1769 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1770 for (TestNetworkCallback c : callbacks) {
1771 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001772 }
1773 }
1774
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001775 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001776 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001777 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001778 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1779 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001780 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1781 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001782 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1783 .addTransportType(TRANSPORT_WIFI).build();
1784 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1785 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001786 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001787 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1788 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1789
1790 // Test unvalidated networks
Chalard Jean407deb72019-11-19 16:14:30 +09001791 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001792 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001793 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001794 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1795 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001796 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1797 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001798 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001799
Paul Jensen3d911462015-06-12 06:40:24 -04001800 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1801 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001802 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001803 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001804 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1805
Chalard Jean407deb72019-11-19 16:14:30 +09001806 cv = registerConnectivityBroadcast(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001807 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001808 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001809 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1810 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001811 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1812 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001813 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001814
Chalard Jean407deb72019-11-19 16:14:30 +09001815 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001816 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001817 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1818 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001819 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001820 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001821 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001822
Chalard Jean407deb72019-11-19 16:14:30 +09001823 cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001824 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001825 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1826 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001827 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001828 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001829
1830 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001831 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001832 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001833 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1834 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001835 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001836 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001837
Paul Jensen3d911462015-06-12 06:40:24 -04001838 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1839 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001840 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001841 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001842 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1843
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001844 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001845 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001846 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001847 genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001848 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001849 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001850 cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001851 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001852 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001853
Paul Jensen3d911462015-06-12 06:40:24 -04001854 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001855 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1856 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001857 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001858
Paul Jensen3d911462015-06-12 06:40:24 -04001859 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001860 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1861 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001862 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001863 }
1864
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001865 private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
1866 final TestNetworkCallback callback = new TestNetworkCallback();
1867 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
1868 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1869 .addTransportType(TRANSPORT_WIFI).build();
1870 mCm.registerNetworkCallback(wifiRequest, callback);
1871 mCm.registerDefaultNetworkCallback(defaultCallback);
1872
1873 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1874 mWiFiNetworkAgent.connect(false);
1875 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1876 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1877
1878 final LinkProperties newLp = new LinkProperties();
1879 final Uri capportUrl = Uri.parse("https://capport.example.com/api");
1880 final CaptivePortalData capportData = new CaptivePortalData.Builder()
1881 .setCaptive(true).build();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001882
1883 final Uri expectedCapportUrl = sanitized ? null : capportUrl;
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001884 newLp.setCaptivePortalApiUrl(capportUrl);
1885 mWiFiNetworkAgent.sendLinkProperties(newLp);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001886 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001887 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001888 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001889 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
1890
1891 final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
1892 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(capportData);
1893 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1894 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
1895 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1896 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001897
1898 final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
1899 assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
1900 assertEquals(expectedCapportData, lp.getCaptivePortalData());
1901 }
1902
1903 @Test
1904 public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
1905 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1906 PERMISSION_DENIED);
1907 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
1908 PERMISSION_DENIED);
1909 doNetworkCallbacksSanitizationTest(true /* sanitized */);
1910 }
1911
1912 @Test
1913 public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
1914 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1915 PERMISSION_GRANTED);
1916 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
1917 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1918 }
1919
1920 @Test
1921 public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
1922 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1923 PERMISSION_DENIED);
1924 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
1925 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1926 }
1927
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001928 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001929 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001930 // This test would be flaky with the default 120ms timer: that is short enough that
1931 // lingered networks are torn down before assertions can be run. We don't want to mock the
1932 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1933 // in detecting races.
1934 mService.mLingerDelayMs = 300;
1935
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001936 NetworkRequest request = new NetworkRequest.Builder()
1937 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1938 .build();
1939 TestNetworkCallback callback = new TestNetworkCallback();
1940 mCm.registerNetworkCallback(request, callback);
1941
1942 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1943 mCm.registerDefaultNetworkCallback(defaultCallback);
1944
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001945 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1946 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1947 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001948
1949 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1950 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1951 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1952
1953 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001954 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1955 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001956 assertEquals(mCellNetworkAgent.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 mWiFiNetworkAgent.connect(true);
1960 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1961 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001962 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001963 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001964 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001965 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001966 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001967 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001968 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001969
1970 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001971 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001972 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001973 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001974 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001975 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001976 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001977 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001978
1979 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001980 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
1981 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001982 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001983 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001984
1985 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001986 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001987 if (i % 2 == 0) {
1988 mWiFiNetworkAgent.adjustScore(-15);
1989 oldNetwork = mWiFiNetworkAgent;
1990 newNetwork = mCellNetworkAgent;
1991 } else {
1992 mWiFiNetworkAgent.adjustScore(15);
1993 oldNetwork = mCellNetworkAgent;
1994 newNetwork = mWiFiNetworkAgent;
1995
1996 }
Chalard Jean059c4262019-09-30 17:51:12 +09001997 callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001998 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1999 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09002000 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002001 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2002 }
2003 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2004
2005 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2006 // if the network is still up.
2007 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002008 // We expect a notification about the capabilities change, and nothing else.
2009 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2010 defaultCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09002011 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002012 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002013
2014 // Wifi no longer satisfies our listen, which is for an unmetered network.
2015 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002016 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2017
2018 // Disconnect our test networks.
2019 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002020 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002021 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002022 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002023 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002024 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002025 waitForIdle();
2026 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002027
2028 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002029 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002030
2031 // Check that a network is only lingered or torn down if it would not satisfy a request even
2032 // if it validated.
2033 request = new NetworkRequest.Builder().clearCapabilities().build();
2034 callback = new TestNetworkCallback();
2035
2036 mCm.registerNetworkCallback(request, callback);
2037
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002038 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002039 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002040 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2041 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002042 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002043 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002044
2045 // Bring up wifi with a score of 20.
2046 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002047 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002048 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002049 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2050 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002051 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002052 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002053
2054 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002055 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2056 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002057 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002058 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002059 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002060
Chalard Jeanfb830762020-02-20 07:32:12 +00002061 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002062 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002063 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanfb830762020-02-20 07:32:12 +00002064 mWiFiNetworkAgent.adjustScore(50);
2065 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002066 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002067 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jeanfb830762020-02-20 07:32:12 +00002068 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002069 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002070 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002071
2072 // Tear down wifi.
2073 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002074 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2075 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002076 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002077 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002078 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002079
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002080 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2081 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002082 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002083 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002084 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002085 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002086 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002087 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002088 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002089 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002090 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002091
2092 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002093 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2094 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002095 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002096 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002097 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2098 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002099 waitForIdle();
2100 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002101
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002102 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002103 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002104 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002105 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2106 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002107 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002108 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002109 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002110 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2111 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002112 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002113 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002114 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002115 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002116
2117 NetworkRequest cellRequest = new NetworkRequest.Builder()
2118 .addTransportType(TRANSPORT_CELLULAR).build();
2119 NetworkCallback noopCallback = new NetworkCallback();
2120 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002121 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2122 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002123 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002124 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002125
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002126 // Similar to the above: lingering can start even after the lingered request is removed.
2127 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002128 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002129 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2130 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002131 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002132 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002133
2134 // Cell is now the default network. Pin it with a cell-specific request.
2135 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2136 mCm.requestNetwork(cellRequest, noopCallback);
2137
2138 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002139 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002140 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002141 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2142 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002143 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002144 // The default request is lingering on cell, but nothing happens to cell, and we send no
2145 // callbacks for it, because it's kept up by cellRequest.
2146 callback.assertNoCallback();
2147 // Now unregister cellRequest and expect cell to start lingering.
2148 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002149 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002150
2151 // Let linger run its course.
2152 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002153 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09002154 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002155
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002156 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2157 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2158 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002159 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002160 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002161 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002162 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002163 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002164 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002165 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2166 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002167 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002168
2169 // Let linger run its course.
Chalard Jean059c4262019-09-30 17:51:12 +09002170 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002171
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002172 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002173 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002174 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2175 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2176 trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002177
2178 mCm.unregisterNetworkCallback(callback);
2179 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002180 mCm.unregisterNetworkCallback(trackDefaultCallback);
2181 }
2182
paulhu86e23eb2019-11-05 18:05:05 +08002183 private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
2184 final String testPackageName = mContext.getPackageName();
2185 when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
2186 .thenReturn(buildPackageInfo(true, uid));
2187 mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
2188 }
2189
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002190 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002191 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002192 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08002193 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Chalard Jean1fa777d2018-02-16 16:07:53 +09002194 NetworkRequest request = new NetworkRequest.Builder()
2195 .clearCapabilities()
2196 .build();
2197 TestNetworkCallback callback = new TestNetworkCallback();
2198 mCm.registerNetworkCallback(request, callback);
2199
2200 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2201 mCm.registerDefaultNetworkCallback(defaultCallback);
2202
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002203 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2204 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002205
2206 mCellNetworkAgent.connect(true);
2207 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2208 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2209
2210 // Wifi comes up and cell lingers.
2211 mWiFiNetworkAgent.connect(true);
2212 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2213 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002214 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002215 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2216
2217 // File a request for cellular, then release it.
2218 NetworkRequest cellRequest = new NetworkRequest.Builder()
2219 .addTransportType(TRANSPORT_CELLULAR).build();
2220 NetworkCallback noopCallback = new NetworkCallback();
2221 mCm.requestNetwork(cellRequest, noopCallback);
2222 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002223 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002224
2225 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002226 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002227 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2228 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2229 lingerTimeoutMs);
2230
2231 // Clean up.
2232 mCm.unregisterNetworkCallback(defaultCallback);
2233 mCm.unregisterNetworkCallback(callback);
2234 }
2235
2236 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002237 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002238 NetworkRequest request = new NetworkRequest.Builder()
2239 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2240 .build();
2241 TestNetworkCallback callback = new TestNetworkCallback();
2242 mCm.registerNetworkCallback(request, callback);
2243
2244 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002245 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002246 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002247 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002248
2249 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002250 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002251 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002252 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002253 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002254
2255 // Cell Remains the default.
2256 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2257
2258 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2259 // it's explicitly selected.
2260 mWiFiNetworkAgent.adjustScore(-40);
2261 mWiFiNetworkAgent.adjustScore(40);
2262 callback.assertNoCallback();
2263
2264 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2265 // wifi even though it's unvalidated.
2266 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002267 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002268 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2269
2270 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2271 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002272 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
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(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002276 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002277
2278 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2279 // network to disconnect.
2280 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002281 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002282
2283 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002284 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002285 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002286 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002287 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002288 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002289 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2290 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2291
2292 // BUG: the network will no longer linger, even though it's validated and outscored.
2293 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002294 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002295 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002296 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002297 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2298 callback.assertNoCallback();
2299
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002300 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
2301 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
2302 // wifi immediately.
2303 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002304 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002305 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002306 mWiFiNetworkAgent.explicitlySelected(true, true);
2307 mWiFiNetworkAgent.connect(false);
2308 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002309 callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002310 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2311 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002312 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002313
2314 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
2315 // Check that the network is not scored specially and that the device prefers cell data.
2316 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002317 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002318 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002319 mWiFiNetworkAgent.explicitlySelected(false, true);
2320 mWiFiNetworkAgent.connect(false);
2321 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2322 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2323
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002324 // Clean up.
2325 mWiFiNetworkAgent.disconnect();
2326 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002327
Chalard Jean059c4262019-09-30 17:51:12 +09002328 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2329 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002330 }
2331
Chalard Jean05ab6812018-05-02 21:14:54 +09002332 private int[] makeIntArray(final int size, final int value) {
2333 final int[] array = new int[size];
2334 Arrays.fill(array, value);
2335 return array;
2336 }
2337
Paul Jensen85cf78e2015-06-25 13:25:07 -04002338 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002339 // Verify NOT_RESTRICTED is set appropriately
2340 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2341 .build().networkCapabilities;
2342 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2343 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2344 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002345 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002346 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2347 } else {
2348 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2349 }
2350
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002351 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002352 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002353 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2354 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002355 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002356 mServiceContext, "testFactory", filter);
2357 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002358 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002359 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002360 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002361 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002362 int expectedRequestCount = 1;
2363 NetworkCallback networkCallback = null;
2364 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2365 // add one.
2366 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002367 assertFalse(testFactory.getMyStartRequested());
2368 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2369 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002370 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002371 mCm.requestNetwork(request, networkCallback);
2372 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002373 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002374 }
Paul Jensen3d911462015-06-12 06:40:24 -04002375 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002376 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2377 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002378
Paul Jensen85cf78e2015-06-25 13:25:07 -04002379 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002380 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002381 // Rather than create a validated network which complicates things by registering it's
2382 // own NetworkRequest during startup, just bump up the score to cancel out the
2383 // unvalidated penalty.
2384 testAgent.adjustScore(40);
2385 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002386
2387 // When testAgent connects, ConnectivityService will re-send us all current requests with
2388 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2389 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002390 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002391 testAgent.connect(false);
2392 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002393 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002394 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002395 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002396
Paul Jensen85cf78e2015-06-25 13:25:07 -04002397 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002398 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002399 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002400 ConnectivityManager.NetworkCallback[] networkCallbacks =
2401 new ConnectivityManager.NetworkCallback[10];
2402 for (int i = 0; i< networkCallbacks.length; i++) {
2403 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2404 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002405 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002406 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2407 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002408 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2409 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002410
Paul Jensen85cf78e2015-06-25 13:25:07 -04002411 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002412 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002413 for (int i = 0; i < networkCallbacks.length; i++) {
2414 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2415 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002416 testFactory.waitForNetworkRequests(expectedRequestCount);
2417 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002418
Paul Jensen85cf78e2015-06-25 13:25:07 -04002419 // Drop the higher scored network.
2420 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002421 // With the default network disconnecting, the requests are sent with score 0 to factories.
2422 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002423 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002424 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002425 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002426 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2427 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002428
2429 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002430 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002431 handlerThread.quit();
2432 }
2433
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002434 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002435 public void testNetworkFactoryRequests() throws Exception {
2436 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2437 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2438 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2439 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2440 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2441 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2442 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2443 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2444 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2445 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2446 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2447 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2448 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2449 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2450 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2451 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2452 }
2453
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002454 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002455 public void testNoMutableNetworkRequests() throws Exception {
2456 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002457 NetworkRequest request1 = new NetworkRequest.Builder()
2458 .addCapability(NET_CAPABILITY_VALIDATED)
2459 .build();
2460 NetworkRequest request2 = new NetworkRequest.Builder()
2461 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2462 .build();
2463
2464 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002465 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2466 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2467 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2468 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002469 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002470
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002471 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002472 public void testMMSonWiFi() throws Exception {
2473 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002474 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002475 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002476 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002477 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002478 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002479 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002480 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002481
Paul Jensene0988542015-06-25 15:30:08 -04002482 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002483 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09002484 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002485 mWiFiNetworkAgent.connect(true);
2486 waitFor(cv);
2487 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002488
Paul Jensene0988542015-06-25 15:30:08 -04002489 // Register MMS NetworkRequest
2490 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2491 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2492 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2493 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002494
Paul Jensene0988542015-06-25 15:30:08 -04002495 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002496 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002497 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002498 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002499 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002500 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002501
Paul Jensene0988542015-06-25 15:30:08 -04002502 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002503 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002504 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002505 verifyActiveNetwork(TRANSPORT_WIFI);
2506 }
2507
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002508 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002509 public void testMMSonCell() throws Exception {
2510 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002511 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09002512 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002513 mCellNetworkAgent.connect(false);
2514 waitFor(cv);
2515 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002516
Paul Jensene0988542015-06-25 15:30:08 -04002517 // Register MMS NetworkRequest
2518 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2519 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2520 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2521 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002522
Paul Jensene0988542015-06-25 15:30:08 -04002523 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002524 TestNetworkAgentWrapper
2525 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002526 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2527 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002528 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002529 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002530
Paul Jensene0988542015-06-25 15:30:08 -04002531 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002532 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002533 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002534 verifyActiveNetwork(TRANSPORT_CELLULAR);
2535 }
2536
lucaslinf3b59b32019-03-26 17:49:49 +08002537 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002538 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002539 // Register network callback.
2540 NetworkRequest request = new NetworkRequest.Builder()
2541 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2542 .build();
2543 TestNetworkCallback callback = new TestNetworkCallback();
2544 mCm.registerNetworkCallback(request, callback);
2545
2546 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002547 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002548 mCellNetworkAgent.connect(true);
2549 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2550
2551 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002552 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002553 mWiFiNetworkAgent.connectWithPartialConnectivity();
2554 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2555 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2556
2557 // Mobile data should be the default network.
2558 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2559 callback.assertNoCallback();
2560
lucaslinf3b59b32019-03-26 17:49:49 +08002561 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2562 // probe.
lucaslin783f2212019-10-22 18:27:33 +08002563 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
lucasline252a742019-03-12 13:08:03 +08002564 // If the user chooses yes to use this partial connectivity wifi, switch the default
2565 // network to wifi and check if wifi becomes valid or not.
2566 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2567 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002568 // If user accepts partial connectivity network,
2569 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002570 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002571 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002572
lucaslinf3b59b32019-03-26 17:49:49 +08002573 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2574 // validated.
2575 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002576 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002577 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2578 mWiFiNetworkAgent);
2579 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2580 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2581
2582 // Disconnect and reconnect wifi with partial connectivity again.
2583 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002584 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002585 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002586 mWiFiNetworkAgent.connectWithPartialConnectivity();
2587 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2588 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2589
2590 // Mobile data should be the default network.
2591 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2592
2593 // If the user chooses no, disconnect wifi immediately.
2594 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2595 false /* always */);
Chalard Jean059c4262019-09-30 17:51:12 +09002596 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002597
2598 // If user accepted partial connectivity before, and device reconnects to that network
2599 // again, but now the network has full connectivity. The network shouldn't contain
2600 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002601 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002602 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002603 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2604 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002605 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002606
lucaslinf3b59b32019-03-26 17:49:49 +08002607 // If user accepted partial connectivity network before,
2608 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2609 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002610 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002611 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002612 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002613 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2614 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002615
lucasline252a742019-03-12 13:08:03 +08002616 // Wifi should be the default network.
2617 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2618 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002619 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002620
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002621 // The user accepted partial connectivity and selected "don't ask again". Now the user
2622 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2623 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002624 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002625 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2626 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002627 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002628 // If user accepted partial connectivity network before,
2629 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2630 // ConnectivityService#updateNetworkInfo().
lucaslinf3b59b32019-03-26 17:49:49 +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 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002635 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
lucaslin783f2212019-10-22 18:27:33 +08002636 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002637
lucaslinf3b59b32019-03-26 17:49:49 +08002638 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2639 // validated.
2640 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2641 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2642 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002643 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002644
2645 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2646 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002647 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002648 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2649 true /* acceptUnvalidated */);
2650
2651 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2652 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2653 // notifyNetworkConnected.
lucaslin783f2212019-10-22 18:27:33 +08002654 mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002655 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002656 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002657 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002658 callback.expectCapabilitiesWith(
2659 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2660 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002661 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002662 }
2663
2664 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002665 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002666 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2667 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2668 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2669 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2670
2671 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2672 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2673 .addCapability(NET_CAPABILITY_VALIDATED).build();
2674 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2675
2676 // Bring up a network with a captive portal.
2677 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002678 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002679 String redirectUrl = "http://android.com/path";
lucaslin783f2212019-10-22 18:27:33 +08002680 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002681 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002682 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002683
2684 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2685 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2686 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2687 .launchCaptivePortalApp();
2688
2689 // Report that the captive portal is dismissed with partial connectivity, and check that
2690 // callbacks are fired.
2691 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002692 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002693 waitForIdle();
2694 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2695 mWiFiNetworkAgent);
2696
2697 // Report partial connectivity is accepted.
lucaslin783f2212019-10-22 18:27:33 +08002698 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002699 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2700 false /* always */);
2701 waitForIdle();
2702 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002703 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002704 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2705 NetworkCapabilities nc =
2706 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2707 mWiFiNetworkAgent);
2708
2709 mCm.unregisterNetworkCallback(captivePortalCallback);
2710 mCm.unregisterNetworkCallback(validatedCallback);
2711 }
2712
2713 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002714 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002715 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2716 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2717 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2718 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2719
2720 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2721 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2722 .addCapability(NET_CAPABILITY_VALIDATED).build();
2723 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002724
2725 // Bring up a network with a captive portal.
2726 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002727 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002728 String firstRedirectUrl = "http://example.com/firstPath";
lucaslin783f2212019-10-22 18:27:33 +08002729 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002730 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002731 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002732
2733 // Take down network.
2734 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002735 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002736 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002737
2738 // Bring up a network with a captive portal.
2739 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002740 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002741 String secondRedirectUrl = "http://example.com/secondPath";
lucaslin783f2212019-10-22 18:27:33 +08002742 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002743 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002744 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002745
2746 // Make captive portal disappear then revalidate.
2747 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
lucaslin783f2212019-10-22 18:27:33 +08002748 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002749 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002750 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002751
2752 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002753 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002754 // Expect no notification to be shown when captive portal disappears by itself
2755 verify(mNotificationManager, never()).notifyAsUser(
2756 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002757
2758 // Break network connectivity.
2759 // Expect NET_CAPABILITY_VALIDATED onLost callback.
lucaslin783f2212019-10-22 18:27:33 +08002760 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002761 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean059c4262019-09-30 17:51:12 +09002762 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002763 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002764
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002765 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002766 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002767 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2768 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2769 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2770 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2771
2772 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2773 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2774 .addCapability(NET_CAPABILITY_VALIDATED).build();
2775 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2776
2777 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002778 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002779 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002780 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002781 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2782
2783 // Check that calling startCaptivePortalApp does nothing.
2784 final int fastTimeoutMs = 100;
2785 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002786 waitForIdle();
2787 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002788 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2789
2790 // Turn into a captive portal.
lucaslin783f2212019-10-22 18:27:33 +08002791 mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002792 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002793 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002794 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002795
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002796 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002797 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002798 waitForIdle();
2799 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2800
2801 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2802 final Bundle testBundle = new Bundle();
2803 final String testKey = "testkey";
2804 final String testValue = "testvalue";
2805 testBundle.putString(testKey, testValue);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09002806 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2807 PERMISSION_GRANTED);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002808 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2809 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2810 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2811 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002812
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002813 // Report that the captive portal is dismissed, and check that callbacks are fired
lucaslin783f2212019-10-22 18:27:33 +08002814 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002815 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002816 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002817 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002818 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2819 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002820
2821 mCm.unregisterNetworkCallback(validatedCallback);
2822 mCm.unregisterNetworkCallback(captivePortalCallback);
2823 }
2824
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002825 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002826 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002827 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2828 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2829 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2830 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2831
2832 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2833 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2834 .addCapability(NET_CAPABILITY_VALIDATED).build();
2835 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2836
2837 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2838 // Bring up a network with a captive portal.
2839 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002840 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002841 String firstRedirectUrl = "http://example.com/firstPath";
2842
lucaslin783f2212019-10-22 18:27:33 +08002843 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002844 mWiFiNetworkAgent.expectDisconnected();
2845 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002846
2847 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002848 }
2849
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09002850 @Test
2851 public void testCaptivePortalApi() throws Exception {
2852 mServiceContext.setPermission(
2853 android.Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
2854
2855 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2856 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2857 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2858 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2859
2860 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2861 final String redirectUrl = "http://example.com/firstPath";
2862
2863 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
2864 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2865
2866 final CaptivePortalData testData = new CaptivePortalData.Builder()
2867 .setUserPortalUrl(Uri.parse(redirectUrl))
2868 .setBytesRemaining(12345L)
2869 .build();
2870
2871 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(testData);
2872
2873 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
2874 lp -> testData.equals(lp.getCaptivePortalData()));
2875
2876 final LinkProperties newLps = new LinkProperties();
2877 newLps.setMtu(1234);
2878 mWiFiNetworkAgent.sendLinkProperties(newLps);
2879 // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
2880 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
2881 lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
2882 }
2883
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002884 private NetworkRequest.Builder newWifiRequestBuilder() {
2885 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2886 }
2887
Etan Cohen836ad572018-12-30 17:59:59 -08002888 /**
2889 * Verify request matching behavior with network specifiers.
2890 *
2891 * Note: this test is somewhat problematic since it involves removing capabilities from
2892 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2893 * as a WTF bug in
2894 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2895 * does work.
2896 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002897 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002898 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002899 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2900 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2901 Parcelable {
2902 @Override
2903 public boolean satisfiedBy(NetworkSpecifier other) {
2904 return true;
2905 }
2906
2907 @Override
2908 public int describeContents() {
2909 return 0;
2910 }
2911
2912 @Override
2913 public void writeToParcel(Parcel dest, int flags) {}
2914
2915 @Override
2916 public NetworkSpecifier redact() {
2917 return null;
2918 }
2919 }
2920
2921 // A network specifier that matches either another LocalNetworkSpecifier with the same
2922 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2923 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2924 private String mString;
2925
2926 LocalStringNetworkSpecifier(String string) {
2927 mString = string;
2928 }
2929
2930 @Override
2931 public boolean satisfiedBy(NetworkSpecifier other) {
2932 if (other instanceof LocalStringNetworkSpecifier) {
2933 return TextUtils.equals(mString,
2934 ((LocalStringNetworkSpecifier) other).mString);
2935 }
2936 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2937 return false;
2938 }
2939
2940 @Override
2941 public int describeContents() {
2942 return 0;
2943 }
2944 @Override
2945 public void writeToParcel(Parcel dest, int flags) {}
2946 }
2947
2948
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002949 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002950 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002951 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002952 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2953 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002954 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2955 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002956 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002957 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002958
2959 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2960 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2961 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002962 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002963 TestNetworkCallback cFoo = new TestNetworkCallback();
2964 TestNetworkCallback cBar = new TestNetworkCallback();
2965 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002966 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002967
2968 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2969 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2970 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002971 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002972 mCm.registerNetworkCallback(rFoo, cFoo);
2973 mCm.registerNetworkCallback(rBar, cBar);
2974
Etan Cohen836ad572018-12-30 17:59:59 -08002975 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2976 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2977
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002978 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002979 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002980 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2981 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2982 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2983 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002984 assertNoCallbacks(cFoo, cBar);
2985
Etan Cohen836ad572018-12-30 17:59:59 -08002986 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002987 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002988 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002989 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2990 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002991 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002992 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2993 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08002994 assertEquals(nsFoo,
2995 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002996 cFoo.assertNoCallback();
2997
Etan Cohen836ad572018-12-30 17:59:59 -08002998 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean059c4262019-09-30 17:51:12 +09002999 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003000 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003001 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003002 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3003 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003004 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003005 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
3006 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08003007 assertEquals(nsBar,
3008 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3009 cBar.assertNoCallback();
3010
3011 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
3012 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3013 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003014 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3015 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08003016 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003017 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
3018 (caps) -> caps.getNetworkSpecifier() == null);
3019 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
3020 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08003021 assertNull(
3022 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3023 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003024 cBar.assertNoCallback();
3025
3026 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean059c4262019-09-30 17:51:12 +09003027 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3028 cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003029 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean059c4262019-09-30 17:51:12 +09003030 c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003031 }
3032
Etan Cohen836ad572018-12-30 17:59:59 -08003033 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003034 }
3035
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003036 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08003037 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09003038 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003039 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07003040 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003041 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003042
Chalard Jean751bb3f2019-06-19 23:29:58 +09003043 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003044 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3045 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07003046 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08003047 mService.requestNetwork(networkCapabilities, null, 0, null,
Qingxi Li9c5d8b92020-01-08 12:51:49 -08003048 ConnectivityManager.TYPE_WIFI, mContext.getPackageName());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003049 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003050
Etan Cohena7434272017-04-03 12:17:51 -07003051 class NonParcelableSpecifier extends NetworkSpecifier {
3052 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
3053 };
3054 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3055 @Override public int describeContents() { return 0; }
3056 @Override public void writeToParcel(Parcel p, int flags) {}
3057 }
Etan Cohena7434272017-04-03 12:17:51 -07003058
Chalard Jean751bb3f2019-06-19 23:29:58 +09003059 final NetworkRequest.Builder builder =
3060 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3061 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07003062 builder.setNetworkSpecifier(new NonParcelableSpecifier());
3063 Parcel parcelW = Parcel.obtain();
3064 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003065 });
Etan Cohena7434272017-04-03 12:17:51 -07003066
Chalard Jean751bb3f2019-06-19 23:29:58 +09003067 final NetworkRequest nr =
3068 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
3069 .setNetworkSpecifier(new ParcelableSpecifier())
3070 .build();
Etan Cohena7434272017-04-03 12:17:51 -07003071 assertNotNull(nr);
3072
Chalard Jean751bb3f2019-06-19 23:29:58 +09003073 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07003074 Parcel parcelW = Parcel.obtain();
3075 nr.writeToParcel(parcelW, 0);
3076 byte[] bytes = parcelW.marshall();
3077 parcelW.recycle();
3078
3079 Parcel parcelR = Parcel.obtain();
3080 parcelR.unmarshall(bytes, 0, bytes.length);
3081 parcelR.setDataPosition(0);
3082 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003083 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003084 }
3085
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003086 @Test
Roshan Piuse38acab2020-01-16 12:17:17 -08003087 public void testNetworkRequestUidSpoofSecurityException() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003088 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07003089 mWiFiNetworkAgent.connect(false);
Roshan Piuse38acab2020-01-16 12:17:17 -08003090 NetworkRequest networkRequest = newWifiRequestBuilder().build();
Etan Cohen859748f2017-04-03 17:42:34 -07003091 TestNetworkCallback networkCallback = new TestNetworkCallback();
Roshan Piuse38acab2020-01-16 12:17:17 -08003092 doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003093 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07003094 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003095 });
Etan Cohen859748f2017-04-03 17:42:34 -07003096 }
3097
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003098 @Test
paulhu3d67f532019-03-22 16:35:06 +08003099 public void testInvalidSignalStrength() {
3100 NetworkRequest r = new NetworkRequest.Builder()
3101 .addCapability(NET_CAPABILITY_INTERNET)
3102 .addTransportType(TRANSPORT_WIFI)
3103 .setSignalStrength(-75)
3104 .build();
3105 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3106 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003107 assertThrows(SecurityException.class, () ->
3108 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003109
Chalard Jean751bb3f2019-06-19 23:29:58 +09003110 assertThrows(SecurityException.class, () ->
3111 mCm.registerNetworkCallback(r, PendingIntent.getService(
3112 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003113
3114 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003115 assertThrows(IllegalArgumentException.class, () ->
3116 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003117
Chalard Jean751bb3f2019-06-19 23:29:58 +09003118 assertThrows(IllegalArgumentException.class, () ->
3119 mCm.requestNetwork(r, PendingIntent.getService(
3120 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003121 }
3122
3123 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003124 public void testRegisterDefaultNetworkCallback() throws Exception {
3125 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3126 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3127 defaultNetworkCallback.assertNoCallback();
3128
3129 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3130 // whenever Wi-Fi is up. Without this, the mobile network agent is
3131 // reaped before any other activity can take place.
3132 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3133 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3134 .addTransportType(TRANSPORT_CELLULAR).build();
3135 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3136 cellNetworkCallback.assertNoCallback();
3137
3138 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003139 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003140 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003141 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3142 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003143 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003144
3145 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003146 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09003147 mWiFiNetworkAgent.connect(true);
3148 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003149 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003150 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003151
3152 // Bring down cell. Expect no default network callback, since it wasn't the default.
3153 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003154 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003155 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003156 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003157
3158 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003159 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003160 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003161 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003162 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003163 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003164
3165 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3166 // followed by AVAILABLE cell.
3167 mWiFiNetworkAgent.disconnect();
3168 cellNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09003169 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003170 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003171 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003172 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3173 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003174 waitForIdle();
3175 assertEquals(null, mCm.getActiveNetwork());
3176
3177 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003178 final TestNetworkAgentWrapper
3179 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003180 final ArraySet<UidRange> ranges = new ArraySet<>();
3181 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003182 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3183 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003184 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003185 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003186 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3187 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3188
3189 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003190 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003191 waitForIdle();
3192 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003193 }
3194
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003195 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003196 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003197 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003198 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003199 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3200 .addTransportType(TRANSPORT_CELLULAR).build();
3201 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3202
3203 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003204 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09003205 mCellNetworkAgent.connect(true);
3206
Erik Kline1d3db322017-02-28 16:20:20 +09003207 // We should get onAvailable(), onCapabilitiesChanged(), and
3208 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3209 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003210 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003211 cellNetworkCallback.assertNoCallback();
3212
3213 // Update LinkProperties.
3214 final LinkProperties lp = new LinkProperties();
3215 lp.setInterfaceName("foonet_data0");
3216 mCellNetworkAgent.sendLinkProperties(lp);
3217 // We should get onLinkPropertiesChanged().
Chalard Jean059c4262019-09-30 17:51:12 +09003218 cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Chalard Jean6f4216f2019-06-05 01:40:32 +09003219 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003220 cellNetworkCallback.assertNoCallback();
3221
Erik Kline1d3db322017-02-28 16:20:20 +09003222 // Suspend the network.
3223 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003224 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3225 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003226 cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003227 cellNetworkCallback.assertNoCallback();
Chiachang Wanga5d8fe82020-02-12 17:01:59 +08003228 assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
Erik Kline1d3db322017-02-28 16:20:20 +09003229
Erik Klineacdd6392016-07-07 16:50:58 +09003230 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003231 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003232 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003233 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3234 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003235 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003236 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003237 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3238
3239 mCellNetworkAgent.resume();
3240 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3241 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003242 cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09003243 cellNetworkCallback.assertNoCallback();
Chiachang Wanga5d8fe82020-02-12 17:01:59 +08003244 assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
Chalard Jean804b8fb2018-01-30 22:41:41 +09003245
3246 dfltNetworkCallback = new TestNetworkCallback();
3247 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3248 // This time onNetworkSuspended should not be called.
3249 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3250 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003251
Erik Klineacdd6392016-07-07 16:50:58 +09003252 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3253 mCm.unregisterNetworkCallback(cellNetworkCallback);
3254 }
3255
Calvin On1f64f3f2016-10-11 15:10:46 -07003256 private void setCaptivePortalMode(int mode) {
3257 ContentResolver cr = mServiceContext.getContentResolver();
3258 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3259 }
3260
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003261 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003262 ContentResolver cr = mServiceContext.getContentResolver();
3263 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003264 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003265 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003266 }
3267
Erik Kline79c6d052018-03-21 07:18:33 -07003268 private void setPrivateDnsSettings(String mode, String specifier) {
3269 final ContentResolver cr = mServiceContext.getContentResolver();
3270 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3271 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3272 mService.updatePrivateDnsSettings();
3273 waitForIdle();
3274 }
3275
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003276 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003277 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3278 assertNotNull(nc);
3279 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3280 }
3281
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003282 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003283 public void testBackgroundNetworks() throws Exception {
3284 // Create a background request. We can't do this ourselves because ConnectivityService
3285 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003286 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08003287 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003288 final NetworkRequest request = new NetworkRequest.Builder().build();
3289 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3290 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3291 final TestNetworkCallback callback = new TestNetworkCallback();
3292 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3293 mCm.registerNetworkCallback(request, callback);
3294 mCm.registerNetworkCallback(fgRequest, fgCallback);
3295
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003296 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003297 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003298 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3299 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003300 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3301
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003302 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003303 mWiFiNetworkAgent.connect(true);
3304
3305 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003306 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003307 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003308 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003309 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003310 fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003311 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003312 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3313 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3314
3315 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003316 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003317 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09003318 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003319 // Expect a network capabilities update sans FOREGROUND.
3320 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003321 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3322 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3323
3324 // File a cell request and check that cell comes into the foreground.
3325 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3326 .addTransportType(TRANSPORT_CELLULAR).build();
3327 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3328 mCm.requestNetwork(cellRequest, cellCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003329 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3330 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003331 // Expect a network capabilities update with FOREGROUND, because the most recent
3332 // request causes its state to change.
Chalard Jean28e6b262019-11-19 21:30:44 +09003333 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003334 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003335 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3336 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3337
3338 // Release the request. The network immediately goes into the background, since it was not
3339 // lingering.
3340 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09003341 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003342 // Expect a network capabilities update sans FOREGROUND.
3343 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003344 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3345 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3346
3347 // Disconnect wifi and check that cell is foreground again.
3348 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003349 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3350 fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003351 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003352 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3353
3354 mCm.unregisterNetworkCallback(callback);
3355 mCm.unregisterNetworkCallback(fgCallback);
3356 }
3357
Hugo Benichi849b81b2017-05-25 13:42:31 +09003358 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003359 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003360 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003361 // Benchmarks connecting and switching performance in the presence of a large number of
3362 // NetworkRequests.
3363 // 1. File NUM_REQUESTS requests.
3364 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3365 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3366 // and NUM_REQUESTS onAvailable callbacks to fire.
3367 // See how long it took.
3368 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003369 final int REGISTER_TIME_LIMIT_MS = 200;
3370 final int CONNECT_TIME_LIMIT_MS = 60;
3371 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003372 final int UNREGISTER_TIME_LIMIT_MS = 20;
3373
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003374 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3375 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3376 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3377 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3378
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003379 for (int i = 0; i < NUM_REQUESTS; i++) {
3380 callbacks[i] = new NetworkCallback() {
3381 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3382 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3383 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003384 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003385
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003386 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003387 for (NetworkCallback cb : callbacks) {
3388 mCm.registerNetworkCallback(request, cb);
3389 }
3390 });
3391
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003392 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003393 // Don't request that the network validate, because otherwise connect() will block until
3394 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3395 // and we won't actually measure anything.
3396 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003397
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003398 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003399 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003400 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003401 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3402 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3403 onAvailableDispatchingDuration));
3404 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3405 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3406 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003407
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003408 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003409 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003410 mWiFiNetworkAgent.adjustScore(40);
3411 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003412
3413 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003414 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003415 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003416 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3417 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3418 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3419 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3420 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003421
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003422 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003423 for (NetworkCallback cb : callbacks) {
3424 mCm.unregisterNetworkCallback(cb);
3425 }
3426 });
3427 }
3428
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003429 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003430 public void testMobileDataAlwaysOn() throws Exception {
paulhu86e23eb2019-11-05 18:05:05 +08003431 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003432 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3433 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3434 .addTransportType(TRANSPORT_CELLULAR).build();
3435 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3436
3437 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3438 handlerThread.start();
3439 NetworkCapabilities filter = new NetworkCapabilities()
3440 .addTransportType(TRANSPORT_CELLULAR)
3441 .addCapability(NET_CAPABILITY_INTERNET);
3442 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3443 mServiceContext, "testFactory", filter);
3444 testFactory.setScoreFilter(40);
3445
3446 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003447 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003448 testFactory.register();
3449 testFactory.waitForNetworkRequests(1);
3450 assertTrue(testFactory.getMyStartRequested());
3451
3452 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003453 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003454 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3455 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003456 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003457 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003458 assertFalse(testFactory.getMyStartRequested());
3459
3460 ContentResolver cr = mServiceContext.getContentResolver();
3461
3462 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003463 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003464 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003465 testFactory.waitForNetworkRequests(2);
3466 assertTrue(testFactory.getMyStartRequested());
3467
3468 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003469 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003470 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003471 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003472 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003473 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003474 testFactory.waitForNetworkRequests(2);
3475 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3476
3477 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003478 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003479 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003480 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003481
3482 // Turn off mobile data always on and expect the request to disappear...
3483 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003484 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003485 testFactory.waitForNetworkRequests(1);
3486
3487 // ... and cell data to be torn down.
Chalard Jean059c4262019-09-30 17:51:12 +09003488 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003489 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003490
3491 testFactory.unregister();
3492 mCm.unregisterNetworkCallback(cellNetworkCallback);
3493 handlerThread.quit();
3494 }
3495
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003496 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003497 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003498 final ContentResolver cr = mServiceContext.getContentResolver();
3499 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3500
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003501 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003502 String[] values = new String[] {null, "0", "1"};
3503 for (int i = 0; i < values.length; i++) {
3504 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003505 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003506 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003507 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003508 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003509 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003510 }
3511
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003512 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003513
3514 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003515 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003516 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003517 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003518 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003519
3520 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003521 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003522 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003523 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003524 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003525
3526 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003527 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003528 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003529 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003530 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003531 }
3532
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003533 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003534 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003535 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003536
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003537 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003538 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003539
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003540 // File a request for cell to ensure it doesn't go down.
3541 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3542 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3543 .addTransportType(TRANSPORT_CELLULAR).build();
3544 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3545
3546 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3547 mCm.registerDefaultNetworkCallback(defaultCallback);
3548
3549 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3550 .addTransportType(TRANSPORT_WIFI)
3551 .addCapability(NET_CAPABILITY_VALIDATED)
3552 .build();
3553 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3554 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3555
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003556 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003557 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003558
3559 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003560 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003561 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003562 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3563 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003564 Network cellNetwork = mCellNetworkAgent.getNetwork();
3565
3566 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003567 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003568 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003569 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3570 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003571 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3572
3573 // Fail validation on wifi.
lucaslin783f2212019-10-22 18:27:33 +08003574 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003575 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003576 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003577 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003578
3579 // Because avoid bad wifi is off, we don't switch to cellular.
3580 defaultCallback.assertNoCallback();
3581 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3582 NET_CAPABILITY_VALIDATED));
3583 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3584 NET_CAPABILITY_VALIDATED));
3585 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3586
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003587 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3588 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003589 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3590 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003591 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003592 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3593
3594 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003595 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3596 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003597 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003598 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3599
3600 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3601 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003602 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003603 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3604 NET_CAPABILITY_VALIDATED));
3605 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3606 NET_CAPABILITY_VALIDATED));
3607 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3608
3609 // Disconnect and reconnect wifi to clear the one-time switch above.
3610 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003611 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003612 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003613 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3614 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003615 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3616
3617 // Fail validation on wifi and expect the dialog to appear.
lucaslin783f2212019-10-22 18:27:33 +08003618 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003619 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003620 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003621 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003622
3623 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003624 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003625 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003626
3627 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003628 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003629 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3630 NET_CAPABILITY_VALIDATED));
3631 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3632 NET_CAPABILITY_VALIDATED));
3633 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3634
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003635 // Simulate the user turning the cellular fallback setting off and then on.
3636 // We switch to wifi and then to cell.
3637 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003638 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003639 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003640 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3641 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003642 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003643 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003644 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3645
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003646 // If cell goes down, we switch to wifi.
3647 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003648 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003649 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003650 validatedWifiCallback.assertNoCallback();
3651
3652 mCm.unregisterNetworkCallback(cellNetworkCallback);
3653 mCm.unregisterNetworkCallback(validatedWifiCallback);
3654 mCm.unregisterNetworkCallback(defaultCallback);
3655 }
3656
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003657 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003658 public void testMeteredMultipathPreferenceSetting() throws Exception {
3659 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003660 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3661
3662 for (int config : Arrays.asList(0, 3, 2)) {
3663 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003664 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003665 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003666 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003667 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003668
3669 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3670 String msg = String.format("config=%d, setting=%s", config, setting);
3671 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3672 }
3673 }
3674 }
3675
Erik Kline3841a482015-11-25 12:49:38 +09003676 /**
3677 * Validate that a satisfied network request does not trigger onUnavailable() once the
3678 * time-out period expires.
3679 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003680 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003681 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003682 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3683 NetworkCapabilities.TRANSPORT_WIFI).build();
3684 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003685 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003686
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003687 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003688 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003689 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003690 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003691
3692 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003693 networkCallback.assertNoCallback();
3694 }
3695
3696 /**
3697 * Validate that a satisfied network request followed by a disconnected (lost) network does
3698 * not trigger onUnavailable() once the time-out period expires.
3699 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003700 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003701 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003702 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3703 NetworkCapabilities.TRANSPORT_WIFI).build();
3704 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003705 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003706
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003707 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003708 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003709 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003710 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003711 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003712 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003713
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003714 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003715 networkCallback.assertNoCallback();
3716 }
3717
3718 /**
3719 * Validate that when a time-out is specified for a network request the onUnavailable()
3720 * callback is called when time-out expires. Then validate that if network request is
3721 * (somehow) satisfied - the callback isn't called later.
3722 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003723 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003724 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003725 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3726 NetworkCapabilities.TRANSPORT_WIFI).build();
3727 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003728 final int timeoutMs = 10;
3729 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003730
3731 // pass timeout and validate that UNAVAILABLE is called
Chalard Jean059c4262019-09-30 17:51:12 +09003732 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Erik Kline3841a482015-11-25 12:49:38 +09003733
3734 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003735 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003736 mWiFiNetworkAgent.connect(false);
3737 networkCallback.assertNoCallback();
3738 }
3739
3740 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003741 * Validate that when a network request is unregistered (cancelled), no posterior event can
3742 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003743 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003744 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003745 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003746 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3747 NetworkCapabilities.TRANSPORT_WIFI).build();
3748 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003749 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003750
Hugo Benichidfb559a2016-12-20 14:57:49 +09003751 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003752 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003753 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3754 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003755 networkCallback.assertNoCallback();
3756
3757 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003758 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003759 mWiFiNetworkAgent.connect(false);
3760 networkCallback.assertNoCallback();
3761 }
3762
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003763 @Test
3764 public void testUnfulfillableNetworkRequest() throws Exception {
3765 runUnfulfillableNetworkRequest(false);
3766 }
3767
3768 @Test
3769 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3770 runUnfulfillableNetworkRequest(true);
3771 }
3772
Etan Cohenddb720a2019-01-08 12:09:18 -08003773 /**
3774 * Validate the callback flow for a factory releasing a request as unfulfillable.
3775 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003776 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003777 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3778 NetworkCapabilities.TRANSPORT_WIFI).build();
3779 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3780
3781 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3782 handlerThread.start();
3783 NetworkCapabilities filter = new NetworkCapabilities()
3784 .addTransportType(TRANSPORT_WIFI)
3785 .addCapability(NET_CAPABILITY_INTERNET);
3786 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3787 mServiceContext, "testFactory", filter);
3788 testFactory.setScoreFilter(40);
3789
3790 // Register the factory and expect it to receive the default request.
Etan Cohenae574a82019-01-08 12:09:18 -08003791 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003792 testFactory.register();
3793 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3794
3795 assertEquals(1, requests.size()); // have 1 request at this point
3796 int origRequestId = requests.valueAt(0).requestId;
3797
3798 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003799 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003800 mCm.requestNetwork(nr, networkCallback);
3801 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3802
3803 int newRequestId = 0;
3804 for (int i = 0; i < requests.size(); ++i) {
3805 if (requests.valueAt(i).requestId != origRequestId) {
3806 newRequestId = requests.valueAt(i).requestId;
3807 break;
3808 }
3809 }
3810
Etan Cohen22e0fc12019-05-23 08:16:20 -07003811 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003812 if (preUnregister) {
3813 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003814
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003815 // Simulate the factory releasing the request as unfulfillable: no-op since
3816 // the callback has already been unregistered (but a test that no exceptions are
3817 // thrown).
3818 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3819 } else {
3820 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003821 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3822
Chalard Jean059c4262019-09-30 17:51:12 +09003823 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003824 testFactory.waitForRequests();
3825
3826 // unregister network callback - a no-op (since already freed by the
3827 // on-unavailable), but should not fail or throw exceptions.
3828 mCm.unregisterNetworkCallback(networkCallback);
3829 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003830
Etan Cohenddb720a2019-01-08 12:09:18 -08003831 testFactory.unregister();
3832 handlerThread.quit();
3833 }
3834
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003835 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3836
Chalard Jeane7b24752019-06-20 16:01:19 +09003837 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003838
3839 private class CallbackValue {
3840 public CallbackType callbackType;
3841 public int error;
3842
3843 public CallbackValue(CallbackType type) {
3844 this.callbackType = type;
3845 this.error = PacketKeepalive.SUCCESS;
3846 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3847 }
3848
3849 public CallbackValue(CallbackType type, int error) {
3850 this.callbackType = type;
3851 this.error = error;
3852 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3853 }
3854
3855 @Override
3856 public boolean equals(Object o) {
3857 return o instanceof CallbackValue &&
3858 this.callbackType == ((CallbackValue) o).callbackType &&
3859 this.error == ((CallbackValue) o).error;
3860 }
3861
3862 @Override
3863 public String toString() {
3864 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3865 }
3866 }
3867
junyulai7c469172019-01-16 20:23:34 +08003868 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003869
3870 @Override
3871 public void onStarted() {
3872 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3873 }
3874
3875 @Override
3876 public void onStopped() {
3877 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3878 }
3879
3880 @Override
3881 public void onError(int error) {
3882 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3883 }
3884
Chalard Jeane7b24752019-06-20 16:01:19 +09003885 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3886 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003887 }
3888
Chalard Jeane7b24752019-06-20 16:01:19 +09003889 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003890 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3891 }
3892
Chalard Jeane7b24752019-06-20 16:01:19 +09003893 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003894 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3895 }
3896
Chalard Jeane7b24752019-06-20 16:01:19 +09003897 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003898 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3899 }
3900 }
3901
junyulai48eac1d42018-12-27 17:25:29 +08003902 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3903
3904 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3905
3906 private class CallbackValue {
3907 public CallbackType callbackType;
3908 public int error;
3909
3910 CallbackValue(CallbackType type) {
3911 this.callbackType = type;
3912 this.error = SocketKeepalive.SUCCESS;
3913 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3914 }
3915
3916 CallbackValue(CallbackType type, int error) {
3917 this.callbackType = type;
3918 this.error = error;
3919 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3920 }
3921
3922 @Override
3923 public boolean equals(Object o) {
3924 return o instanceof CallbackValue
3925 && this.callbackType == ((CallbackValue) o).callbackType
3926 && this.error == ((CallbackValue) o).error;
3927 }
3928
3929 @Override
3930 public String toString() {
3931 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3932 error);
3933 }
3934 }
3935
3936 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003937 private final Executor mExecutor;
3938
3939 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3940 mExecutor = executor;
3941 }
junyulai48eac1d42018-12-27 17:25:29 +08003942
3943 @Override
3944 public void onStarted() {
3945 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3946 }
3947
3948 @Override
3949 public void onStopped() {
3950 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3951 }
3952
3953 @Override
3954 public void onError(int error) {
3955 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3956 }
3957
Chalard Jeane7b24752019-06-20 16:01:19 +09003958 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3959 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3960
junyulai48eac1d42018-12-27 17:25:29 +08003961 }
3962
Chalard Jeane7b24752019-06-20 16:01:19 +09003963 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003964 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3965 }
3966
Chalard Jeane7b24752019-06-20 16:01:19 +09003967 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003968 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3969 }
3970
Chalard Jeane7b24752019-06-20 16:01:19 +09003971 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003972 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3973 }
junyulai7c469172019-01-16 20:23:34 +08003974
3975 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003976 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08003977 CallbackValue cv = mCallbacks.peek();
3978 assertNull("Unexpected callback: " + cv, cv);
3979 }
junyulai48eac1d42018-12-27 17:25:29 +08003980 }
3981
Chalard Jeane7b24752019-06-20 16:01:19 +09003982 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003983 // Ensure the network is disconnected before we do anything.
3984 if (mWiFiNetworkAgent != null) {
3985 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3986 }
3987
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003988 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09003989 ConditionVariable cv = registerConnectivityBroadcast(1);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003990 mWiFiNetworkAgent.connect(true);
3991 waitFor(cv);
3992 verifyActiveNetwork(TRANSPORT_WIFI);
3993 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003994 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003995 return mWiFiNetworkAgent.getNetwork();
3996 }
3997
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003998 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07003999 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004000 public void testPacketKeepalives() throws Exception {
4001 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4002 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4003 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4004 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4005 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4006
Nathan Harold63dd8132018-02-14 13:09:45 -08004007 final int validKaInterval = 15;
4008 final int invalidKaInterval = 9;
4009
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004010 LinkProperties lp = new LinkProperties();
4011 lp.setInterfaceName("wlan12");
4012 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4013 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4014 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4015 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4016
4017 Network notMyNet = new Network(61234);
4018 Network myNet = connectKeepaliveNetwork(lp);
4019
4020 TestKeepaliveCallback callback = new TestKeepaliveCallback();
4021 PacketKeepalive ka;
4022
4023 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08004024 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004025 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4026
Nathan Harold63dd8132018-02-14 13:09:45 -08004027 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004028 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4029
Nathan Harold63dd8132018-02-14 13:09:45 -08004030 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004031 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4032
Nathan Harold63dd8132018-02-14 13:09:45 -08004033 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004034 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4035
Nathan Harold63dd8132018-02-14 13:09:45 -08004036 // NAT-T is only supported for IPv4.
4037 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4038 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004039
Nathan Harold63dd8132018-02-14 13:09:45 -08004040 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004041 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4042
Nathan Harold63dd8132018-02-14 13:09:45 -08004043 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004044 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4045
Nathan Harold63dd8132018-02-14 13:09:45 -08004046 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004047 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4048
Nathan Harold63dd8132018-02-14 13:09:45 -08004049 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004050 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4051
4052 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004053 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08004054 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004055 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004056 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004057 ka.stop();
4058 callback.expectStopped();
4059
4060 // Check that deleting the IP address stops the keepalive.
4061 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08004062 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004063 callback.expectStarted();
4064 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4065 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4066 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4067 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4068 mWiFiNetworkAgent.sendLinkProperties(lp);
4069
4070 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004071 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004072 callback.expectStarted();
4073 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004074 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004075 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4076
4077 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004078 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004079 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004080 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004081 ka.stop();
4082
4083 // Reconnect.
4084 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004085 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004086
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004087 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4088 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004089 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004090 callback.expectStarted();
4091
4092 // The second one gets slot 2.
4093 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4094 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004095 PacketKeepalive ka2 = mCm.startNattKeepalive(
4096 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004097 callback2.expectStarted();
4098
4099 // Now stop the first one and create a third. This also gets slot 1.
4100 ka.stop();
4101 callback.expectStopped();
4102
4103 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4104 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004105 PacketKeepalive ka3 = mCm.startNattKeepalive(
4106 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004107 callback3.expectStarted();
4108
4109 ka2.stop();
4110 callback2.expectStopped();
4111
4112 ka3.stop();
4113 callback3.expectStopped();
4114 }
Udam Sainib7c24872016-01-04 12:16:14 -08004115
Xiao Maa4637112019-02-07 15:03:57 +09004116 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09004117 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
4118 throws Exception {
junyulai06835112019-01-03 18:50:15 +08004119 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004120 final Executor executorInline = (Runnable r) -> r.run();
4121 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08004122 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004123 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004124 }
junyulai06835112019-01-03 18:50:15 +08004125
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004126 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004127 public void testNattSocketKeepalives() throws Exception {
4128 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4129 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08004130 }
4131
4132 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004133 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08004134 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004135 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004136 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4137 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4138 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4139 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4140 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4141
4142 final int validKaInterval = 15;
4143 final int invalidKaInterval = 9;
4144
4145 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004146 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4147 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004148
junyulai48eac1d42018-12-27 17:25:29 +08004149 LinkProperties lp = new LinkProperties();
4150 lp.setInterfaceName("wlan12");
4151 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4152 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4153 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4154 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4155
4156 Network notMyNet = new Network(61234);
4157 Network myNet = connectKeepaliveNetwork(lp);
4158
junyulai7c469172019-01-16 20:23:34 +08004159 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004160
4161 // Attempt to start keepalives with invalid parameters and check for errors.
4162 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004163 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4164 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4165 ka.start(validKaInterval);
4166 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4167 }
junyulai48eac1d42018-12-27 17:25:29 +08004168
4169 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004170 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4171 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4172 ka.start(invalidKaInterval);
4173 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4174 }
junyulai48eac1d42018-12-27 17:25:29 +08004175
4176 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004177 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4178 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4179 ka.start(validKaInterval);
4180 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4181 }
junyulai48eac1d42018-12-27 17:25:29 +08004182
4183 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004184 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4185 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4186 ka.start(validKaInterval);
4187 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4188 }
junyulai48eac1d42018-12-27 17:25:29 +08004189
4190 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004191 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4192 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4193 ka.start(validKaInterval);
4194 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4195 }
junyulai48eac1d42018-12-27 17:25:29 +08004196
4197 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004198 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4199 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4200 ka.start(validKaInterval);
4201 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4202 }
junyulai48eac1d42018-12-27 17:25:29 +08004203
4204 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004205 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004206 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4207 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4208 ka.start(validKaInterval);
4209 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004210 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004211 ka.stop();
4212 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004213
junyulai0c666972019-03-04 22:45:36 +08004214 // Check that keepalive could be restarted.
4215 ka.start(validKaInterval);
4216 callback.expectStarted();
4217 ka.stop();
4218 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004219
junyulai0c666972019-03-04 22:45:36 +08004220 // Check that keepalive can be restarted without waiting for callback.
4221 ka.start(validKaInterval);
4222 callback.expectStarted();
4223 ka.stop();
4224 ka.start(validKaInterval);
4225 callback.expectStopped();
4226 callback.expectStarted();
4227 ka.stop();
4228 callback.expectStopped();
4229 }
junyulai7c469172019-01-16 20:23:34 +08004230
junyulai48eac1d42018-12-27 17:25:29 +08004231 // Check that deleting the IP address stops the keepalive.
4232 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004233 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4234 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4235 ka.start(validKaInterval);
4236 callback.expectStarted();
4237 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4238 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4239 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4240 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4241 mWiFiNetworkAgent.sendLinkProperties(lp);
4242 }
junyulai48eac1d42018-12-27 17:25:29 +08004243
4244 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004245 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4246 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4247 ka.start(validKaInterval);
4248 callback.expectStarted();
4249 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004250 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004251 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004252
junyulai0c666972019-03-04 22:45:36 +08004253 // ... and that stopping it after that has no adverse effects.
4254 waitForIdle();
4255 final Network myNetAlias = myNet;
4256 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4257 ka.stop();
4258 callback.assertNoCallback();
4259 }
junyulai48eac1d42018-12-27 17:25:29 +08004260
4261 // Reconnect.
4262 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004263 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08004264
4265 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4266 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004267 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004268 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4269 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4270 ka.start(validKaInterval);
4271 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004272
junyulai0c666972019-03-04 22:45:36 +08004273 // The second one gets slot 2.
4274 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004275 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4276 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004277 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4278 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4279 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4280 ka2.start(validKaInterval);
4281 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004282
junyulai0c666972019-03-04 22:45:36 +08004283 ka.stop();
4284 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004285
junyulai0c666972019-03-04 22:45:36 +08004286 ka2.stop();
4287 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004288
junyulai0c666972019-03-04 22:45:36 +08004289 testSocket.close();
4290 testSocket2.close();
4291 }
4292 }
junyulai06835112019-01-03 18:50:15 +08004293
junyulai15178152019-03-27 11:00:37 +08004294 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004295 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4296 // assertFalse(isUdpPortInUse(srcPort));
4297 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004298
junyulai06835112019-01-03 18:50:15 +08004299 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004300 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004301 mWiFiNetworkAgent = null;
4302 }
4303
4304 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004305 public void testTcpSocketKeepalives() throws Exception {
4306 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004307 }
4308
4309 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4310 final int srcPortV4 = 12345;
4311 final int srcPortV6 = 23456;
4312 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4313 final InetAddress myIPv6 = InetAddress.getByName("::1");
4314
4315 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004316
4317 final LinkProperties lp = new LinkProperties();
4318 lp.setInterfaceName("wlan12");
4319 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4320 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4321 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4322 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4323
4324 final Network notMyNet = new Network(61234);
4325 final Network myNet = connectKeepaliveNetwork(lp);
4326
4327 final Socket testSocketV4 = new Socket();
4328 final Socket testSocketV6 = new Socket();
4329
junyulai7c469172019-01-16 20:23:34 +08004330 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004331
4332 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4333 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004334 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4335 notMyNet, testSocketV4, executor, callback)) {
4336 ka.start(validKaInterval);
4337 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4338 }
Xiao Maa4637112019-02-07 15:03:57 +09004339
4340 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004341 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4342 myNet, testSocketV4, executor, callback)) {
4343 ka.start(validKaInterval);
4344 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4345 }
Xiao Maa4637112019-02-07 15:03:57 +09004346
4347 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004348 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4349 myNet, testSocketV6, executor, callback)) {
4350 ka.start(validKaInterval);
4351 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4352 }
Xiao Maa4637112019-02-07 15:03:57 +09004353
4354 // Bind the socket address
4355 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4356 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4357
4358 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004359 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4360 myNet, testSocketV4, executor, callback)) {
4361 ka.start(validKaInterval);
4362 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4363 }
Xiao Maa4637112019-02-07 15:03:57 +09004364
4365 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004366 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4367 myNet, testSocketV6, executor, callback)) {
4368 ka.start(validKaInterval);
4369 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4370 }
Xiao Maa4637112019-02-07 15:03:57 +09004371
4372 testSocketV4.close();
4373 testSocketV6.close();
4374
4375 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004376 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004377 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004378 }
4379
junyulai0c666972019-03-04 22:45:36 +08004380 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004381 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4382 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4383 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4384 final int validKaInterval = 15;
4385
4386 // Prepare the target network.
4387 LinkProperties lp = new LinkProperties();
4388 lp.setInterfaceName("wlan12");
4389 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4390 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4391 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004392 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4393 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004394
4395 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4396
4397 // Prepare the target file descriptor, keep only one instance.
4398 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004399 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4400 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004401 final ParcelFileDescriptor testPfd =
4402 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4403 testSocket.close();
4404 assertTrue(isUdpPortInUse(srcPort));
4405
4406 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4407 // block.
4408 try (SocketKeepalive ka = mCm.createNattKeepalive(
4409 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4410 ka.start(validKaInterval);
4411 callback.expectStarted();
4412 ka.stop();
4413 callback.expectStopped();
4414 }
4415
4416 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4417 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4418 // address.
4419 assertTrue(isUdpPortInUse(srcPort));
4420 final InetSocketAddress sa =
4421 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4422 assertEquals(anyIPv4, sa.getAddress());
4423
4424 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004425 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4426 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004427
4428 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004429 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004430 mWiFiNetworkAgent = null;
4431 }
4432
4433 private static boolean isUdpPortInUse(int port) {
4434 try (DatagramSocket ignored = new DatagramSocket(port)) {
4435 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004436 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004437 return true;
4438 }
4439 }
4440
junyulai48eac1d42018-12-27 17:25:29 +08004441 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004442 public void testGetCaptivePortalServerUrl() throws Exception {
4443 String url = mCm.getCaptivePortalServerUrl();
4444 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4445 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004446
4447 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004448 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004449 synchronized(sLock) {
4450 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004451 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004452 }
4453 return sNetwork != null;
4454 }
4455 }
4456
Chalard Jeane7b24752019-06-20 16:01:19 +09004457 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004458 synchronized(sLock) {
4459 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004460 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004461 }
4462 return sNetwork == null;
4463 }
4464 }
4465 }
4466
4467 private void assertPinnedToWifiWithCellDefault() {
4468 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4469 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4470 }
4471
4472 private void assertPinnedToWifiWithWifiDefault() {
4473 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4474 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4475 }
4476
4477 private void assertNotPinnedToWifi() {
4478 assertNull(mCm.getBoundNetworkForProcess());
4479 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4480 }
4481
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004482 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004483 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004484 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4485 .addTransportType(TRANSPORT_WIFI)
4486 .build();
4487 assertNull(mCm.getBoundNetworkForProcess());
4488
4489 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4490 assertNull(mCm.getBoundNetworkForProcess());
4491
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004492 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004493 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004494 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004495 mWiFiNetworkAgent.connect(false);
4496
4497 // When wi-fi connects, expect to be pinned.
4498 assertTrue(TestNetworkPinner.awaitPin(100));
4499 assertPinnedToWifiWithCellDefault();
4500
4501 // Disconnect and expect the pin to drop.
4502 mWiFiNetworkAgent.disconnect();
4503 assertTrue(TestNetworkPinner.awaitUnpin(100));
4504 assertNotPinnedToWifi();
4505
4506 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004507 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004508 mWiFiNetworkAgent.connect(false);
4509 assertFalse(TestNetworkPinner.awaitPin(100));
4510 assertNotPinnedToWifi();
4511
4512 // Pinning while connected causes the pin to take effect immediately.
4513 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4514 assertTrue(TestNetworkPinner.awaitPin(100));
4515 assertPinnedToWifiWithCellDefault();
4516
4517 // Explicitly unpin and expect to use the default network again.
4518 TestNetworkPinner.unpin();
4519 assertNotPinnedToWifi();
4520
4521 // Disconnect cell and wifi.
Chalard Jean407deb72019-11-19 16:14:30 +09004522 ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004523 mCellNetworkAgent.disconnect();
4524 mWiFiNetworkAgent.disconnect();
4525 waitFor(cv);
4526
4527 // Pinning takes effect even if the pinned network is the default when the pin is set...
4528 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004529 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004530 mWiFiNetworkAgent.connect(false);
4531 assertTrue(TestNetworkPinner.awaitPin(100));
4532 assertPinnedToWifiWithWifiDefault();
4533
4534 // ... and is maintained even when that network is no longer the default.
Chalard Jean407deb72019-11-19 16:14:30 +09004535 cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004536 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004537 mCellNetworkAgent.connect(true);
4538 waitFor(cv);
4539 assertPinnedToWifiWithCellDefault();
4540 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004541
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004542 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004543 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004544 // We can only have 99 callbacks, because MultipathPolicyTracker is
4545 // already one of them.
4546 final int MAX_REQUESTS = 99;
4547 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004548 final int INTENTS = 10;
4549 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4550
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004551 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004552 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004553
Hugo Benichi893a7622017-09-29 09:34:08 +09004554 int j = 0;
4555 while (j++ < CALLBACKS / 2) {
4556 NetworkCallback cb = new NetworkCallback();
4557 mCm.requestNetwork(networkRequest, cb);
4558 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004559 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004560 while (j++ < CALLBACKS) {
4561 NetworkCallback cb = new NetworkCallback();
4562 mCm.registerNetworkCallback(networkRequest, cb);
4563 registered.add(cb);
4564 }
4565 j = 0;
4566 while (j++ < INTENTS / 2) {
4567 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4568 mCm.requestNetwork(networkRequest, pi);
4569 registered.add(pi);
4570 }
4571 while (j++ < INTENTS) {
4572 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4573 mCm.registerNetworkCallback(networkRequest, pi);
4574 registered.add(pi);
4575 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004576
Hugo Benichi893a7622017-09-29 09:34:08 +09004577 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004578 assertThrows(TooManyRequestsException.class, () ->
4579 mCm.requestNetwork(networkRequest, new NetworkCallback())
4580 );
4581 assertThrows(TooManyRequestsException.class, () ->
4582 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4583 );
4584 assertThrows(TooManyRequestsException.class, () ->
4585 mCm.requestNetwork(networkRequest,
4586 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4587 );
4588 assertThrows(TooManyRequestsException.class, () ->
4589 mCm.registerNetworkCallback(networkRequest,
4590 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4591 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004592
Hugo Benichi893a7622017-09-29 09:34:08 +09004593 for (Object o : registered) {
4594 if (o instanceof NetworkCallback) {
4595 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004596 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004597 if (o instanceof PendingIntent) {
4598 mCm.unregisterNetworkCallback((PendingIntent)o);
4599 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004600 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004601 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004602
4603 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4604 for (int i = 0; i < MAX_REQUESTS; i++) {
4605 NetworkCallback networkCallback = new NetworkCallback();
4606 mCm.requestNetwork(networkRequest, networkCallback);
4607 mCm.unregisterNetworkCallback(networkCallback);
4608 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004609 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004610
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004611 for (int i = 0; i < MAX_REQUESTS; i++) {
4612 NetworkCallback networkCallback = new NetworkCallback();
4613 mCm.registerNetworkCallback(networkRequest, networkCallback);
4614 mCm.unregisterNetworkCallback(networkCallback);
4615 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004616 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004617
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004618 for (int i = 0; i < MAX_REQUESTS; i++) {
4619 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004620 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004621 mCm.requestNetwork(networkRequest, pendingIntent);
4622 mCm.unregisterNetworkCallback(pendingIntent);
4623 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004624 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004625
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004626 for (int i = 0; i < MAX_REQUESTS; i++) {
4627 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004628 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004629 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4630 mCm.unregisterNetworkCallback(pendingIntent);
4631 }
4632 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004633
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004634 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004635 public void testNetworkInfoOfTypeNone() throws Exception {
Chalard Jean407deb72019-11-19 16:14:30 +09004636 ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004637
4638 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004639 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004640 assertNull(mCm.getActiveNetworkInfo());
4641
4642 Network[] allNetworks = mCm.getAllNetworks();
4643 assertLength(1, allNetworks);
4644 Network network = allNetworks[0];
4645 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4646 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4647
4648 final NetworkRequest request =
4649 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4650 final TestNetworkCallback callback = new TestNetworkCallback();
4651 mCm.registerNetworkCallback(request, callback);
4652
Hugo Benichic1014502017-07-19 10:10:52 +09004653 // Bring up wifi aware network.
lucaslin783f2212019-10-22 18:27:33 +08004654 wifiAware.connect(false, false, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004655 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004656
4657 assertNull(mCm.getActiveNetworkInfo());
4658 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004659 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004660 // of this test. Fix it and uncomment the assert below.
4661 //assertEmpty(mCm.getAllNetworkInfo());
4662
Hugo Benichic1014502017-07-19 10:10:52 +09004663 // Disconnect wifi aware network.
4664 wifiAware.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09004665 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004666 mCm.unregisterNetworkCallback(callback);
4667
4668 verifyNoNetwork();
4669 if (broadcastCV.block(10)) {
4670 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4671 }
4672 }
4673
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004674 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004675 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4676 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4677 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4678 assertNull(mCm.getNetworkForType(TYPE_NONE));
4679 assertNull(mCm.getLinkProperties(TYPE_NONE));
4680 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4681
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004682 assertThrows(IllegalArgumentException.class,
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004683 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004684
4685 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004686 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4687 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004688 // TODO: let test context have configuration application target sdk version
4689 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004690 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4691 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4692 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004693 }
4694
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004695 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004696 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004697 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4698 .addTransportType(TRANSPORT_WIFI).build();
4699 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4700 mCm.registerNetworkCallback(networkRequest, networkCallback);
4701
4702 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004703 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004704 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4705 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4706 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4707 lp.addLinkAddress(myIpv4Address);
4708 lp.addRoute(myIpv4DefaultRoute);
4709
4710 // Verify direct routes are added when network agent is first registered in
4711 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004712 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004713 networkAgent.connect(true);
Chalard Jean059c4262019-09-30 17:51:12 +09004714 networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
4715 networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
4716 CallbackEntry.LinkPropertiesChanged cbi =
4717 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004718 networkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004719 networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004720 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4721 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004722 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004723 Arrays.asList(myIpv4DefaultRoute));
4724 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4725 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4726
4727 // Verify direct routes are added during subsequent link properties updates.
4728 LinkProperties newLp = new LinkProperties(lp);
4729 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4730 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4731 newLp.addLinkAddress(myIpv6Address1);
4732 newLp.addLinkAddress(myIpv6Address2);
4733 networkAgent.sendLinkProperties(newLp);
Chalard Jean059c4262019-09-30 17:51:12 +09004734 cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004735 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004736 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004737 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4738 Arrays.asList(myIpv4DefaultRoute));
4739 mCm.unregisterNetworkCallback(networkCallback);
4740 }
4741
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004742 @Test
4743 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004744 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4745 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004746
Varun Anandd33cbc62019-02-07 14:13:13 -08004747 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4748 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4749
4750 LinkProperties cellLp = new LinkProperties();
4751 cellLp.setInterfaceName(MOBILE_IFNAME);
4752 LinkProperties wifiLp = new LinkProperties();
4753 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004754
4755 // Simple connection should have updated ifaces
4756 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004757 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004758 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004759 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004760 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4761 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004762 reset(mStatsService);
4763
4764 // Default network switch should update ifaces.
4765 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004766 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004767 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004768 assertEquals(wifiLp, mService.getActiveLinkProperties());
4769 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004770 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4771 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004772 reset(mStatsService);
4773
4774 // Disconnect should update ifaces.
4775 mWiFiNetworkAgent.disconnect();
4776 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004777 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004778 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4779 eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004780 reset(mStatsService);
4781
4782 // Metered change should update ifaces
4783 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4784 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004785 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004786 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4787 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004788 reset(mStatsService);
4789
4790 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4791 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004792 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004793 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4794 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004795 reset(mStatsService);
4796
4797 // Captive portal change shouldn't update ifaces
4798 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4799 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004800 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004801 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4802 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004803 reset(mStatsService);
4804
4805 // Roaming change should update ifaces
4806 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4807 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004808 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004809 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4810 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004811 reset(mStatsService);
4812 }
4813
Erik Klinee89953b2018-01-11 16:11:10 +09004814 @Test
4815 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004816 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004817
4818 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004819 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004820
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004821 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09004822 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004823 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004824 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004825
4826 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004827 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004828 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4829 // "is-reachable" testing in order to not program netd with unreachable
4830 // nameservers that it might try repeated to validate.
4831 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004832 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4833 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004834 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004835 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4836 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004837 mCellNetworkAgent.sendLinkProperties(cellLp);
4838 mCellNetworkAgent.connect(false);
4839 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004840
4841 verify(mMockDnsResolver, times(1)).createNetworkCache(
4842 eq(mCellNetworkAgent.getNetwork().netId));
4843 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004844 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004845 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004846
4847 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4848 mCellNetworkAgent.sendLinkProperties(cellLp);
4849 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004850 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004851 mResolverParamsParcelCaptor.capture());
4852 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4853 assertEquals(1, resolvrParams.servers.length);
4854 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004855 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004856 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004857 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004858
4859 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4860 mCellNetworkAgent.sendLinkProperties(cellLp);
4861 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004862 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004863 mResolverParamsParcelCaptor.capture());
4864 resolvrParams = mResolverParamsParcelCaptor.getValue();
4865 assertEquals(2, resolvrParams.servers.length);
4866 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004867 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004868 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004869 assertEquals(2, resolvrParams.tlsServers.length);
4870 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004871 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004872 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004873
4874 final String TLS_SPECIFIER = "tls.example.com";
4875 final String TLS_SERVER6 = "2001:db8:53::53";
4876 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4877 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004878 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4879 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4880
Erik Kline117e7f32018-03-04 21:01:01 +09004881 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004882 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004883 mResolverParamsParcelCaptor.capture());
4884 resolvrParams = mResolverParamsParcelCaptor.getValue();
4885 assertEquals(2, resolvrParams.servers.length);
4886 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004887 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004888 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004889 }
4890
Erik Kline79c6d052018-03-21 07:18:33 -07004891 @Test
lucaslin783f2212019-10-22 18:27:33 +08004892 public void testPrivateDnsNotification() throws Exception {
4893 NetworkRequest request = new NetworkRequest.Builder()
4894 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4895 .build();
4896 TestNetworkCallback callback = new TestNetworkCallback();
4897 mCm.registerNetworkCallback(request, callback);
4898 // Bring up wifi.
4899 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4900 mWiFiNetworkAgent.connect(false);
4901 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4902 // Private DNS resolution failed, checking if the notification will be shown or not.
4903 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4904 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4905 waitForIdle();
4906 // If network validation failed, NetworkMonitor will re-evaluate the network.
4907 // ConnectivityService should filter the redundant notification. This part is trying to
4908 // simulate that situation and check if ConnectivityService could filter that case.
4909 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4910 waitForIdle();
4911 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
4912 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4913 // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
4914 // shown.
4915 mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
4916 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4917 waitForIdle();
4918 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
4919 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
4920 // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
4921 // shown again.
4922 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4923 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4924 waitForIdle();
4925 verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
4926 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4927 }
4928
4929 @Test
Erik Kline79c6d052018-03-21 07:18:33 -07004930 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004931 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004932 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004933
4934 // The default on Android is opportunistic mode ("Automatic").
4935 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4936
dalyk1fcb7392018-03-05 12:42:22 -05004937 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4938 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4939 .addTransportType(TRANSPORT_CELLULAR).build();
4940 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4941
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004942 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07004943 waitForIdle();
4944 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004945 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004946 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004947
4948 final LinkProperties cellLp = new LinkProperties();
4949 cellLp.setInterfaceName(MOBILE_IFNAME);
4950 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4951 // "is-reachable" testing in order to not program netd with unreachable
4952 // nameservers that it might try repeated to validate.
4953 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4954 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4955 MOBILE_IFNAME));
4956 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4957 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4958 MOBILE_IFNAME));
4959 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4960 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4961
4962 mCellNetworkAgent.sendLinkProperties(cellLp);
4963 mCellNetworkAgent.connect(false);
4964 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004965 verify(mMockDnsResolver, times(1)).createNetworkCache(
4966 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08004967 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004968 mResolverParamsParcelCaptor.capture());
4969 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4970 assertEquals(2, resolvrParams.tlsServers.length);
4971 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004972 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07004973 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004974 assertEquals(2, resolvrParams.tlsServers.length);
4975 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004976 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004977 reset(mMockDnsResolver);
Chalard Jean059c4262019-09-30 17:51:12 +09004978 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
4979 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004980 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004981 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4982 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4983 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004984 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004985 assertFalse(cbi.getLp().isPrivateDnsActive());
4986 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004987
4988 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004989 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004990 mResolverParamsParcelCaptor.capture());
4991 resolvrParams = mResolverParamsParcelCaptor.getValue();
4992 assertEquals(2, resolvrParams.servers.length);
4993 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004994 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004995 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004996 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004997
4998 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004999 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005000 mResolverParamsParcelCaptor.capture());
5001 resolvrParams = mResolverParamsParcelCaptor.getValue();
5002 assertEquals(2, resolvrParams.servers.length);
5003 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005004 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08005005 assertEquals(2, resolvrParams.tlsServers.length);
5006 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005007 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08005008 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005009 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005010
dalyk1fcb7392018-03-05 12:42:22 -05005011 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5012 // Can't test dns configuration for strict mode without properly mocking
5013 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean059c4262019-09-30 17:51:12 +09005014 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005015 mCellNetworkAgent);
5016 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005017 assertTrue(cbi.getLp().isPrivateDnsActive());
5018 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005019 }
5020
5021 @Test
5022 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5023 // The default on Android is opportunistic mode ("Automatic").
5024 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5025
5026 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5027 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5028 .addTransportType(TRANSPORT_CELLULAR).build();
5029 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5030
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005031 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05005032 waitForIdle();
5033 LinkProperties lp = new LinkProperties();
5034 mCellNetworkAgent.sendLinkProperties(lp);
5035 mCellNetworkAgent.connect(false);
5036 waitForIdle();
Chalard Jean059c4262019-09-30 17:51:12 +09005037 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
5038 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05005039 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005040 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
5041 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
5042 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005043 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005044 assertFalse(cbi.getLp().isPrivateDnsActive());
5045 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005046 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005047 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005048
5049 // Send a validation event for a server that is not part of the current
5050 // resolver config. The validation event should be ignored.
5051 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5052 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5053 cellNetworkCallback.assertNoCallback();
5054
5055 // Add a dns server to the LinkProperties.
5056 LinkProperties lp2 = new LinkProperties(lp);
5057 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5058 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean059c4262019-09-30 17:51:12 +09005059 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005060 mCellNetworkAgent);
5061 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005062 assertFalse(cbi.getLp().isPrivateDnsActive());
5063 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005064 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005065 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005066
5067 // Send a validation event containing a hostname that is not part of
5068 // the current resolver config. The validation event should be ignored.
5069 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5070 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5071 cellNetworkCallback.assertNoCallback();
5072
5073 // Send a validation event where validation failed.
5074 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5075 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5076 cellNetworkCallback.assertNoCallback();
5077
5078 // Send a validation event where validation succeeded for a server in
5079 // the current resolver config. A LinkProperties callback with updated
5080 // private dns fields should be sent.
5081 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5082 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean059c4262019-09-30 17:51:12 +09005083 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005084 mCellNetworkAgent);
5085 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005086 assertTrue(cbi.getLp().isPrivateDnsActive());
5087 assertNull(cbi.getLp().getPrivateDnsServerName());
5088 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005089
5090 // The private dns fields in LinkProperties should be preserved when
5091 // the network agent sends unrelated changes.
5092 LinkProperties lp3 = new LinkProperties(lp2);
5093 lp3.setMtu(1300);
5094 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean059c4262019-09-30 17:51:12 +09005095 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005096 mCellNetworkAgent);
5097 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005098 assertTrue(cbi.getLp().isPrivateDnsActive());
5099 assertNull(cbi.getLp().getPrivateDnsServerName());
5100 checkDnsServers(cbi.getLp(), dnsServers);
5101 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05005102
5103 // Removing the only validated server should affect the private dns
5104 // fields in LinkProperties.
5105 LinkProperties lp4 = new LinkProperties(lp3);
5106 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5107 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean059c4262019-09-30 17:51:12 +09005108 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005109 mCellNetworkAgent);
5110 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005111 assertFalse(cbi.getLp().isPrivateDnsActive());
5112 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005113 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005114 checkDnsServers(cbi.getLp(), dnsServers);
5115 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005116 }
5117
Rubin Xu1bb5c082017-09-05 18:40:49 +01005118 private void checkDirectlyConnectedRoutes(Object callbackObj,
5119 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5120 assertTrue(callbackObj instanceof LinkProperties);
5121 LinkProperties lp = (LinkProperties) callbackObj;
5122
5123 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5124 expectedRoutes.addAll(otherRoutes);
5125 for (LinkAddress address : linkAddresses) {
5126 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5127 // Duplicates in linkAddresses are considered failures
5128 assertTrue(expectedRoutes.add(localRoute));
5129 }
5130 List<RouteInfo> observedRoutes = lp.getRoutes();
5131 assertEquals(expectedRoutes.size(), observedRoutes.size());
5132 assertTrue(observedRoutes.containsAll(expectedRoutes));
5133 }
5134
dalyk1fcb7392018-03-05 12:42:22 -05005135 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5136 assertTrue(callbackObj instanceof LinkProperties);
5137 LinkProperties lp = (LinkProperties) callbackObj;
5138 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5139 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5140 }
5141
Chalard Jean0b214af2018-01-12 17:22:49 +09005142 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005143 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09005144 final int uid = Process.myUid();
5145
5146 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005147 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005148 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5149 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005150 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005151 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5152 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5153 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005154 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5155 .addTransportType(TRANSPORT_WIFI).build();
5156 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005157 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005158 .addTransportType(TRANSPORT_VPN).build();
5159 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005160 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005161 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5162 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005163 mCm.registerDefaultNetworkCallback(defaultCallback);
5164 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005165
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005166 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09005167 mWiFiNetworkAgent.connect(false);
5168
5169 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005170 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005171 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005172 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005173 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005174 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005175
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005176 final TestNetworkAgentWrapper
5177 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean0b214af2018-01-12 17:22:49 +09005178 final ArraySet<UidRange> ranges = new ArraySet<>();
5179 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005180 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5181 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005182 // VPN networks do not satisfy the default request and are automatically validated
5183 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005184 assertFalse(NetworkMonitorUtils.isValidationRequired(
5185 vpnNetworkAgent.getNetworkCapabilities()));
lucaslin783f2212019-10-22 18:27:33 +08005186 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005187
Chalard Jean0b214af2018-01-12 17:22:49 +09005188 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005189 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005190 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005191
5192 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005193 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005194 wifiNetworkCallback.assertNoCallback();
5195 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005196 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5197 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005198
Chalard Jean059c4262019-09-30 17:51:12 +09005199 genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005200 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005201 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
Chalard Jean059c4262019-09-30 17:51:12 +09005202 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005203 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005204
5205 ranges.clear();
5206 vpnNetworkAgent.setUids(ranges);
5207
Chalard Jean059c4262019-09-30 17:51:12 +09005208 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005209 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005210 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005211 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005212
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005213 // TODO : The default network callback should actually get a LOST call here (also see the
5214 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5215 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5216 // can't currently update their UIDs without disconnecting, so this does not matter too
5217 // much, but that is the reason the test here has to check for an update to the
5218 // capabilities instead of the expected LOST then AVAILABLE.
Chalard Jean059c4262019-09-30 17:51:12 +09005219 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005220
Chalard Jean0b214af2018-01-12 17:22:49 +09005221 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005222 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005223 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005224
5225 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005226 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005227 wifiNetworkCallback.assertNoCallback();
5228 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005229 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5230 // happen outside of the test, ConnectivityService does not rematch callbacks.
Chalard Jean059c4262019-09-30 17:51:12 +09005231 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005232
5233 mWiFiNetworkAgent.disconnect();
5234
Chalard Jean059c4262019-09-30 17:51:12 +09005235 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5236 genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5237 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005238 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005239 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005240
5241 vpnNetworkAgent.disconnect();
5242
Chalard Jean059c4262019-09-30 17:51:12 +09005243 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005244 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005245 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005246 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5247 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005248 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005249
5250 mCm.unregisterNetworkCallback(genericNetworkCallback);
5251 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5252 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005253 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005254 }
Chalard Jean26400492018-04-18 20:18:38 +09005255
5256 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005257 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09005258 final int uid = Process.myUid();
5259
5260 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5261 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005262
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005263 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09005264 mWiFiNetworkAgent.connect(true);
5265
5266 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5267 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5268
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005269 TestNetworkAgentWrapper
5270 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09005271 final ArraySet<UidRange> ranges = new ArraySet<>();
5272 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005273 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5274 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005275 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5276 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005277 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005278
5279 defaultCallback.assertNoCallback();
5280 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5281
5282 vpnNetworkAgent.disconnect();
5283 defaultCallback.assertNoCallback();
5284
Varun Anand4fa80e82019-02-06 10:13:38 -08005285 mCm.unregisterNetworkCallback(defaultCallback);
5286 }
5287
5288 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005289 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005290 final int uid = Process.myUid();
5291
5292 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5293 mCm.registerDefaultNetworkCallback(defaultCallback);
5294
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005295 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005296 mWiFiNetworkAgent.connect(true);
5297
5298 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5299 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5300
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005301 TestNetworkAgentWrapper
5302 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005303 final ArraySet<UidRange> ranges = new ArraySet<>();
5304 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005305 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5306 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005307 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
5308 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005309 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005310
Chalard Jean26400492018-04-18 20:18:38 +09005311 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5312 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5313
5314 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005315 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean26400492018-04-18 20:18:38 +09005316 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5317
Chalard Jean26400492018-04-18 20:18:38 +09005318 mCm.unregisterNetworkCallback(defaultCallback);
5319 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005320
5321 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005322 public void testVpnUnvalidated() throws Exception {
5323 final TestNetworkCallback callback = new TestNetworkCallback();
5324 mCm.registerDefaultNetworkCallback(callback);
5325
5326 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005327 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005328 mEthernetNetworkAgent.connect(true);
5329 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5330 callback.assertNoCallback();
5331
5332 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5333 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005334 final TestNetworkAgentWrapper
5335 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005336 final ArraySet<UidRange> ranges = new ArraySet<>();
5337 ranges.add(new UidRange(uid, uid));
5338 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5339 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005340 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
5341 false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005342 mMockVpn.connect();
5343
5344 // Even though the VPN is unvalidated, it becomes the default network for our app.
5345 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5346 // TODO: this looks like a spurious callback.
Chalard Jean059c4262019-09-30 17:51:12 +09005347 callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005348 callback.assertNoCallback();
5349
5350 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5351 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5352 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5353
5354 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5355 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5356 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5357
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005358 assertFalse(NetworkMonitorUtils.isValidationRequired(
5359 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005360 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005361 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005362
5363 // Pretend that the VPN network validates.
lucaslin783f2212019-10-22 18:27:33 +08005364 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005365 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5366 // Expect to see the validated capability, but no other changes, because the VPN is already
5367 // the default network for the app.
5368 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5369 callback.assertNoCallback();
5370
5371 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005372 callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005373 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5374 }
5375
5376 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005377 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005378 final int uid = Process.myUid();
5379
5380 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5381 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5382 .removeCapability(NET_CAPABILITY_NOT_VPN)
5383 .addTransportType(TRANSPORT_VPN)
5384 .build();
5385 NetworkCapabilities nc;
5386 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5387 vpnNetworkCallback.assertNoCallback();
5388
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005389 final TestNetworkAgentWrapper
5390 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005391 final ArraySet<UidRange> ranges = new ArraySet<>();
5392 ranges.add(new UidRange(uid, uid));
5393 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5394 mMockVpn.connect();
5395 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005396 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5397 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005398
5399 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5400 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5401 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5402 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5403 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5404 // For safety reasons a VPN without underlying networks is considered metered.
5405 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5406
5407 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005408 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005409 mCellNetworkAgent.connect(true);
5410
5411 mService.setUnderlyingNetworksForVpn(
5412 new Network[] { mCellNetworkAgent.getNetwork() });
5413
Chalard Jean6f4216f2019-06-05 01:40:32 +09005414 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5415 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005416 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005417 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005418
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005419 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005420 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5421 mWiFiNetworkAgent.connect(true);
5422
5423 mService.setUnderlyingNetworksForVpn(
5424 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5425
Chalard Jean6f4216f2019-06-05 01:40:32 +09005426 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5427 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005428 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005429 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005430
5431 // Don't disconnect, but note the VPN is not using wifi any more.
5432 mService.setUnderlyingNetworksForVpn(
5433 new Network[] { mCellNetworkAgent.getNetwork() });
5434
Chalard Jean6f4216f2019-06-05 01:40:32 +09005435 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5436 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005437 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005438 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005439
5440 // Use Wifi but not cell. Note the VPN is now unmetered.
5441 mService.setUnderlyingNetworksForVpn(
5442 new Network[] { mWiFiNetworkAgent.getNetwork() });
5443
Chalard Jean6f4216f2019-06-05 01:40:32 +09005444 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5445 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005446 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005447 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005448
5449 // Use both again.
5450 mService.setUnderlyingNetworksForVpn(
5451 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5452
Chalard Jean6f4216f2019-06-05 01:40:32 +09005453 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5454 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005455 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005456 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005457
Chalard Jean6b65ec72018-05-18 22:02:56 +09005458 // Disconnect cell. Receive update without even removing the dead network from the
5459 // underlying networks – it's dead anyway. Not metered any more.
5460 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005461 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5462 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005463 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005464 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005465
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005466 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005467 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005468 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5469 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +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 mMockVpn.disconnect();
5474 }
junyulai4a192e22018-06-13 15:00:37 +08005475
Mike Yuf9729752018-08-17 15:22:05 +08005476 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005477 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005478 final int uid = Process.myUid();
5479
5480 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5481 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5482 .removeCapability(NET_CAPABILITY_NOT_VPN)
5483 .addTransportType(TRANSPORT_VPN)
5484 .build();
5485 NetworkCapabilities nc;
5486 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5487 vpnNetworkCallback.assertNoCallback();
5488
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005489 final TestNetworkAgentWrapper
5490 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005491 final ArraySet<UidRange> ranges = new ArraySet<>();
5492 ranges.add(new UidRange(uid, uid));
5493 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5494 mMockVpn.connect();
5495 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005496 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5497 false /* isStrictMode */);
Varun Anand4fa80e82019-02-06 10:13:38 -08005498
5499 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5500 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5501 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5502 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5503 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5504 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5505 // In case of no default network, VPN is considered metered.
5506 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5507
5508 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005509 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005510 mCellNetworkAgent.connect(true);
5511
Chalard Jean6f4216f2019-06-05 01:40:32 +09005512 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5513 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005514 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005515 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005516
5517 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005518 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005519 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5520 mWiFiNetworkAgent.connect(true);
5521
Chalard Jean6f4216f2019-06-05 01:40:32 +09005522 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5523 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005524 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005525 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005526
5527 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5528 // the capabilities.
5529 mCellNetworkAgent.disconnect();
5530
5531 // Disconnect wifi too. Now we have no default network.
5532 mWiFiNetworkAgent.disconnect();
5533
Chalard Jean6f4216f2019-06-05 01:40:32 +09005534 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5535 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005536 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005537 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005538
5539 mMockVpn.disconnect();
5540 }
5541
5542 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005543 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005544 // Returns true by default when no network is available.
5545 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005546 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005547 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5548 mWiFiNetworkAgent.connect(true);
5549 waitForIdle();
5550
5551 assertFalse(mCm.isActiveNetworkMetered());
5552 }
5553
5554 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005555 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005556 // Returns true by default when no network is available.
5557 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005558 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005559 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5560 mCellNetworkAgent.connect(true);
5561 waitForIdle();
5562
5563 assertTrue(mCm.isActiveNetworkMetered());
5564 }
5565
5566 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005567 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005568 // Returns true by default when no network is available.
5569 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005570 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005571 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5572 mCellNetworkAgent.connect(true);
5573 waitForIdle();
5574 assertTrue(mCm.isActiveNetworkMetered());
5575
5576 // Connect VPN network. By default it is using current default network (Cell).
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005577 TestNetworkAgentWrapper
5578 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005579 final ArraySet<UidRange> ranges = new ArraySet<>();
5580 final int uid = Process.myUid();
5581 ranges.add(new UidRange(uid, uid));
5582 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5583 mMockVpn.setUids(ranges);
5584 vpnNetworkAgent.connect(true);
5585 mMockVpn.connect();
5586 waitForIdle();
5587 // Ensure VPN is now the active network.
5588 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5589
5590 // Expect VPN to be metered.
5591 assertTrue(mCm.isActiveNetworkMetered());
5592
5593 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005594 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005595 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5596 mWiFiNetworkAgent.connect(true);
5597 waitForIdle();
5598 // VPN should still be the active network.
5599 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5600
5601 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5602 assertFalse(mCm.isActiveNetworkMetered());
5603
5604 // Disconnecting Cell should not affect VPN's meteredness.
5605 mCellNetworkAgent.disconnect();
5606 waitForIdle();
5607
5608 assertFalse(mCm.isActiveNetworkMetered());
5609
5610 // Disconnect WiFi; Now there is no platform default network.
5611 mWiFiNetworkAgent.disconnect();
5612 waitForIdle();
5613
5614 // VPN without any underlying networks is treated as metered.
5615 assertTrue(mCm.isActiveNetworkMetered());
5616
5617 vpnNetworkAgent.disconnect();
5618 mMockVpn.disconnect();
5619 }
5620
5621 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005622 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005623 // Returns true by default when no network is available.
5624 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005625 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005626 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5627 mCellNetworkAgent.connect(true);
5628 waitForIdle();
5629 assertTrue(mCm.isActiveNetworkMetered());
5630
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005631 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005632 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5633 mWiFiNetworkAgent.connect(true);
5634 waitForIdle();
5635 assertFalse(mCm.isActiveNetworkMetered());
5636
5637 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005638 TestNetworkAgentWrapper
5639 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005640 final ArraySet<UidRange> ranges = new ArraySet<>();
5641 final int uid = Process.myUid();
5642 ranges.add(new UidRange(uid, uid));
5643 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5644 mMockVpn.setUids(ranges);
5645 vpnNetworkAgent.connect(true);
5646 mMockVpn.connect();
5647 waitForIdle();
5648 // Ensure VPN is now the active network.
5649 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5650 // VPN is using Cell
5651 mService.setUnderlyingNetworksForVpn(
5652 new Network[] { mCellNetworkAgent.getNetwork() });
5653 waitForIdle();
5654
5655 // Expect VPN to be metered.
5656 assertTrue(mCm.isActiveNetworkMetered());
5657
5658 // VPN is now using WiFi
5659 mService.setUnderlyingNetworksForVpn(
5660 new Network[] { mWiFiNetworkAgent.getNetwork() });
5661 waitForIdle();
5662
5663 // Expect VPN to be unmetered
5664 assertFalse(mCm.isActiveNetworkMetered());
5665
5666 // VPN is using Cell | WiFi.
5667 mService.setUnderlyingNetworksForVpn(
5668 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5669 waitForIdle();
5670
5671 // Expect VPN to be metered.
5672 assertTrue(mCm.isActiveNetworkMetered());
5673
5674 // VPN is using WiFi | Cell.
5675 mService.setUnderlyingNetworksForVpn(
5676 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5677 waitForIdle();
5678
5679 // Order should not matter and VPN should still be metered.
5680 assertTrue(mCm.isActiveNetworkMetered());
5681
5682 // VPN is not using any underlying networks.
5683 mService.setUnderlyingNetworksForVpn(new Network[0]);
5684 waitForIdle();
5685
5686 // VPN without underlying networks is treated as metered.
5687 assertTrue(mCm.isActiveNetworkMetered());
5688
5689 vpnNetworkAgent.disconnect();
5690 mMockVpn.disconnect();
5691 }
5692
5693 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005694 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005695 // Returns true by default when no network is available.
5696 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005697 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005698 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5699 mWiFiNetworkAgent.connect(true);
5700 waitForIdle();
5701 assertFalse(mCm.isActiveNetworkMetered());
5702
5703 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005704 TestNetworkAgentWrapper
5705 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005706 final ArraySet<UidRange> ranges = new ArraySet<>();
5707 final int uid = Process.myUid();
5708 ranges.add(new UidRange(uid, uid));
5709 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5710 mMockVpn.setUids(ranges);
5711 vpnNetworkAgent.connect(true);
5712 mMockVpn.connectAsAlwaysMetered();
5713 waitForIdle();
5714 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5715
5716 // VPN is tracking current platform default (WiFi).
5717 mService.setUnderlyingNetworksForVpn(null);
5718 waitForIdle();
5719
5720 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5721 assertTrue(mCm.isActiveNetworkMetered());
5722
5723 // VPN explicitly declares WiFi as its underlying network.
5724 mService.setUnderlyingNetworksForVpn(
5725 new Network[] { mWiFiNetworkAgent.getNetwork() });
5726 waitForIdle();
5727
5728 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5729 assertTrue(mCm.isActiveNetworkMetered());
5730
5731 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5732 // anyways suppose to be metered.
5733 mWiFiNetworkAgent.disconnect();
5734 waitForIdle();
5735
5736 assertTrue(mCm.isActiveNetworkMetered());
5737
5738 vpnNetworkAgent.disconnect();
5739 }
5740
5741 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005742 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005743 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5744 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5745 .addTransportType(TRANSPORT_CELLULAR)
5746 .build();
5747 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5748
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005749 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005750 mCellNetworkAgent.connect(true);
5751 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5752
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005753 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08005754 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5755
5756 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005757 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005758 cellNetworkCallback.assertNoCallback();
5759
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005760 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005761 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5762
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005763 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005764 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5765
5766 // Restrict the network based on UID rule and NOT_METERED capability change.
5767 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5768 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5769 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5770 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5771 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5772 mCellNetworkAgent);
5773 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005774 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005775 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5776
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005777 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005778 cellNetworkCallback.assertNoCallback();
5779
5780 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005781 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005782 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005783 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005784 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005785 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005786 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5787 cellNetworkCallback.assertNoCallback();
5788
5789 mCm.unregisterNetworkCallback(cellNetworkCallback);
5790 }
5791
5792 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005793 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005794 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5795 mCm.registerDefaultNetworkCallback(defaultCallback);
5796
5797 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005798 setUidRulesChanged(RULE_REJECT_ALL);
5799 setUidRulesChanged(RULE_NONE);
5800 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005801 defaultCallback.assertNoCallback();
5802
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005803 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005804 mCellNetworkAgent.connect(true);
5805 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5806 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5807
5808 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005809 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08005810 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5811 mWiFiNetworkAgent.connect(true);
5812 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5813
5814 // Switch to METERED network. Restrict the use of the network.
5815 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005816 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005817 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5818
5819 // Network becomes NOT_METERED.
5820 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5821 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5822 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5823
5824 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005825 setRestrictBackgroundChanged(true);
5826 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005827 defaultCallback.assertNoCallback();
5828
5829 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005830 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005831 defaultCallback.assertNoCallback();
5832
5833 mCm.unregisterNetworkCallback(defaultCallback);
5834 }
5835
Chalard Jean143124b2019-12-03 22:13:37 +09005836 @Test
5837 public final void testLoseTrusted() throws Exception {
5838 final NetworkRequest trustedRequest = new NetworkRequest.Builder()
5839 .addCapability(NET_CAPABILITY_TRUSTED)
5840 .build();
5841 final TestNetworkCallback trustedCallback = new TestNetworkCallback();
5842 mCm.requestNetwork(trustedRequest, trustedCallback);
5843
5844 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5845 mCellNetworkAgent.connect(true);
5846 trustedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5847 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005848 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005849
5850 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5851 mWiFiNetworkAgent.connect(true);
Chalard Jean10c8d542020-02-20 07:32:12 +00005852 trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean143124b2019-12-03 22:13:37 +09005853 verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005854 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005855
5856 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
Chalard Jean143124b2019-12-03 22:13:37 +09005857 trustedCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5858 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005859 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005860
5861 mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
5862 trustedCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5863 verify(mNetworkManagementService).clearDefaultNetId();
5864
5865 mCm.unregisterNetworkCallback(trustedCallback);
5866 }
5867
Chalard Jeanb6ec0762019-12-03 16:12:33 +09005868 @Ignore // 40%+ flakiness : figure out why and re-enable.
Chalard Jean587758b2019-11-29 16:41:50 +09005869 @Test
5870 public final void testBatteryStatsNetworkType() throws Exception {
5871 final LinkProperties cellLp = new LinkProperties();
5872 cellLp.setInterfaceName("cell0");
5873 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5874 mCellNetworkAgent.connect(true);
5875 waitForIdle();
5876 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5877 TYPE_MOBILE);
5878 reset(mBatteryStatsService);
5879
5880 final LinkProperties wifiLp = new LinkProperties();
5881 wifiLp.setInterfaceName("wifi0");
5882 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
5883 mWiFiNetworkAgent.connect(true);
5884 waitForIdle();
5885 verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(),
5886 TYPE_WIFI);
5887 reset(mBatteryStatsService);
5888
Chalard Jean587758b2019-11-29 16:41:50 +09005889 mCellNetworkAgent.disconnect();
5890
5891 cellLp.setInterfaceName("wifi0");
5892 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5893 mCellNetworkAgent.connect(true);
5894 waitForIdle();
5895 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5896 TYPE_MOBILE);
5897 }
5898
junyulai4a192e22018-06-13 15:00:37 +08005899 /**
5900 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5901 */
5902 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5903 InterfaceConfiguration cfg = new InterfaceConfiguration();
5904 cfg.setHardwareAddress("11:22:33:44:55:66");
5905 cfg.setLinkAddress(la);
5906 return cfg;
5907 }
5908
5909 /**
5910 * Make expected stack link properties, copied from Nat464Xlat.
5911 */
5912 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5913 LinkAddress clatAddress = la;
5914 LinkProperties stacked = new LinkProperties();
5915 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5916 RouteInfo ipv4Default = new RouteInfo(
5917 new LinkAddress(Inet4Address.ANY, 0),
5918 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5919 stacked.addRoute(ipv4Default);
5920 stacked.addLinkAddress(clatAddress);
5921 return stacked;
5922 }
5923
5924 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005925 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08005926 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5927 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005928 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5929 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005930 final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(),
5931 MOBILE_IFNAME);
5932 final RouteInfo hostRoute = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
5933 final RouteInfo ipv4Default = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
5934 final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(),
5935 CLAT_PREFIX + MOBILE_IFNAME);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005936
junyulai4a192e22018-06-13 15:00:37 +08005937 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5938 .addTransportType(TRANSPORT_CELLULAR)
5939 .addCapability(NET_CAPABILITY_INTERNET)
5940 .build();
5941 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5942 mCm.registerNetworkCallback(networkRequest, networkCallback);
5943
Lorenzo Colittid593e292019-02-19 13:21:56 +09005944 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005945 final LinkProperties cellLp = new LinkProperties();
5946 cellLp.setInterfaceName(MOBILE_IFNAME);
5947 cellLp.addLinkAddress(myIpv6);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005948 cellLp.addRoute(defaultRoute);
5949 cellLp.addRoute(hostRoute);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005950 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005951 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005952 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005953 reset(mMockNetd);
Chalard Jean587758b2019-11-29 16:41:50 +09005954 reset(mBatteryStatsService);
junyulai4a192e22018-06-13 15:00:37 +08005955
Lorenzo Colittid593e292019-02-19 13:21:56 +09005956 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005957 mCellNetworkAgent.connect(true);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005958 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
Chalard Jean587758b2019-11-29 16:41:50 +09005959 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005960
5961 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005962 verify(mNetworkManagementService, times(1)).addRoute(eq(cellNetId), eq(defaultRoute));
5963 verify(mNetworkManagementService, times(1)).addRoute(eq(cellNetId), eq(hostRoute));
Luke Huanga24d5d82019-04-09 18:41:49 +08005964 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
Chalard Jean587758b2019-11-29 16:41:50 +09005965 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5966 TYPE_MOBILE);
Luke Huanga24d5d82019-04-09 18:41:49 +08005967
junyulai4a192e22018-06-13 15:00:37 +08005968 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005969 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005970
Lorenzo Colittid593e292019-02-19 13:21:56 +09005971 // Switching default network updates TCP buffer sizes.
5972 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5973
5974 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5975 // the NAT64 prefix was removed because one was never discovered.
5976 cellLp.addLinkAddress(myIpv4);
5977 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005978 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005979 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005980 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005981
Chalard Jean587758b2019-11-29 16:41:50 +09005982 // Make sure BatteryStats was not told about any v4- interfaces, as none should have
5983 // come online yet.
5984 waitForIdle();
5985 verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt());
5986
Lorenzo Colittid593e292019-02-19 13:21:56 +09005987 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005988 verifyNoMoreInteractions(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005989 reset(mNetworkManagementService);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005990 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005991 reset(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005992 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5993 .thenReturn(getClatInterfaceConfig(myIpv4));
Lorenzo Colittid593e292019-02-19 13:21:56 +09005994
5995 // Remove IPv4 address. Expect prefix discovery to be started again.
5996 cellLp.removeLinkAddress(myIpv4);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005997 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005998 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005999 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006000
6001 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006002 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006003 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09006004 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6005 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006006 LinkProperties lpBeforeClat = networkCallback.expectCallback(
Chalard Jean059c4262019-09-30 17:51:12 +09006007 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006008 assertEquals(0, lpBeforeClat.getStackedLinks().size());
6009 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
6010 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6011
6012 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08006013 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean059c4262019-09-30 17:51:12 +09006014 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006015 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
6016 .getStackedLinks();
6017 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006018 verify(mNetworkManagementService).addRoute(eq(cellNetId), eq(stackedDefault));
junyulai4a192e22018-06-13 15:00:37 +08006019
6020 // Change trivial linkproperties and see if stacked link is preserved.
6021 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
6022 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006023 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08006024
6025 List<LinkProperties> stackedLpsAfterChange =
6026 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
6027 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
6028 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
6029
Luke Huang65914772019-03-16 00:31:46 +08006030 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08006031 mResolverParamsParcelCaptor.capture());
6032 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
6033 assertEquals(1, resolvrParams.servers.length);
6034 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08006035
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09006036 for (final LinkProperties stackedLp : stackedLpsAfterChange) {
6037 verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(),
6038 TYPE_MOBILE);
6039 }
Chalard Jean587758b2019-11-29 16:41:50 +09006040
Lorenzo Colittid593e292019-02-19 13:21:56 +09006041 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
6042 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08006043 cellLp.addLinkAddress(myIpv4);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006044 cellLp.addRoute(ipv4Default);
junyulai4a192e22018-06-13 15:00:37 +08006045 mCellNetworkAgent.sendLinkProperties(cellLp);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006046 verify(mNetworkManagementService).addRoute(eq(cellNetId), eq(stackedDefault));
Chalard Jean059c4262019-09-30 17:51:12 +09006047 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09006048 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08006049 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08006050
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006051 // As soon as stop is called, the linkproperties lose the stacked interface.
Chalard Jean059c4262019-09-30 17:51:12 +09006052 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006053 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
6054 LinkProperties expected = new LinkProperties(cellLp);
6055 expected.setNat64Prefix(kNat64Prefix);
6056 assertEquals(expected, actualLpAfterIpv4);
6057 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
6058
6059 // The interface removed callback happens but has no effect after stop is called.
6060 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6061 networkCallback.assertNoCallback();
6062
Lorenzo Colittid593e292019-02-19 13:21:56 +09006063 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006064 verifyNoMoreInteractions(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006065 reset(mNetworkManagementService);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006066 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006067 reset(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006068 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6069 .thenReturn(getClatInterfaceConfig(myIpv4));
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006070
Lorenzo Colittid593e292019-02-19 13:21:56 +09006071 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6072 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6073 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006074 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6075 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006076
6077 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006078 cellLp.removeLinkAddress(myIpv4);
6079 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6080 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6081 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006082 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006083 verify(mNetworkManagementService, times(1)).removeRoute(eq(cellNetId), eq(ipv4Default));
Luke Huang65914772019-03-16 00:31:46 +08006084 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006085 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6086 kNat64PrefixString, 96);
Chalard Jean059c4262019-09-30 17:51:12 +09006087 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006088 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6089
Lorenzo Colittid593e292019-02-19 13:21:56 +09006090
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006091 // Clat iface comes up. Expect stacked link to be added.
6092 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006093 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6094 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006095
6096 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006097 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6098 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006099 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6100 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006101 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006102 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6103 (lp) -> lp.getStackedLinks().size() == 0);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006104
6105 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08006106 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006107 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006108 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08006109 mCm.unregisterNetworkCallback(networkCallback);
6110 }
Chiachang Wanga6093042018-09-28 22:42:48 +08006111
6112 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006113 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08006114 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6115 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6116 .addCapability(NET_CAPABILITY_INTERNET)
6117 .build();
6118 mCm.registerNetworkCallback(networkRequest, networkCallback);
6119
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006120 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08006121 final LinkProperties cellLp = new LinkProperties();
6122 cellLp.setInterfaceName(MOBILE_IFNAME);
6123 mCellNetworkAgent.sendLinkProperties(cellLp);
6124 reset(mNetworkManagementService);
6125 mCellNetworkAgent.connect(true);
6126 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6127 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6128 eq(ConnectivityManager.TYPE_MOBILE));
6129
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006130 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006131 final LinkProperties wifiLp = new LinkProperties();
6132 wifiLp.setInterfaceName(WIFI_IFNAME);
6133 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6134
6135 // Network switch
6136 reset(mNetworkManagementService);
6137 mWiFiNetworkAgent.connect(true);
6138 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006139 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006140 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6141 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6142 eq(ConnectivityManager.TYPE_WIFI));
6143 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6144
6145 // Disconnect wifi and switch back to cell
6146 reset(mNetworkManagementService);
6147 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006148 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006149 assertNoCallbacks(networkCallback);
6150 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6151 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6152 eq(ConnectivityManager.TYPE_MOBILE));
6153
6154 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006155 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006156 wifiLp.setInterfaceName(WIFI_IFNAME);
6157 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6158 mWiFiNetworkAgent.connect(true);
6159 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006160 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006161 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6162
6163 // Disconnect cell
6164 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006165 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006166 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006167 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006168 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6169 // sent as network being switched. Ensure rule removal for cell will not be triggered
6170 // unexpectedly before network being removed.
6171 waitForIdle();
6172 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006173 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6174 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08006175 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006176
6177 // Disconnect wifi
Chalard Jean407deb72019-11-19 16:14:30 +09006178 ConditionVariable cv = registerConnectivityBroadcast(1);
Chiachang Wanga6093042018-09-28 22:42:48 +08006179 reset(mNetworkManagementService);
6180 mWiFiNetworkAgent.disconnect();
6181 waitFor(cv);
6182 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6183
6184 // Clean up
6185 mCm.unregisterNetworkCallback(networkCallback);
6186 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006187
Chalard Jeane7b24752019-06-20 16:01:19 +09006188 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006189 String[] values = tcpBufferSizes.split(",");
6190 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6191 String wmemValues = String.join(" ", values[3], values[4], values[5]);
Chalard Jeane7b24752019-06-20 16:01:19 +09006192 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006193 reset(mMockNetd);
6194 }
6195
6196 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006197 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006198 final String testTcpBufferSizes = "1,2,3,4,5,6";
paulhu66269b32019-08-30 19:24:36 +08006199 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6200 .addTransportType(TRANSPORT_CELLULAR)
6201 .addCapability(NET_CAPABILITY_INTERNET)
6202 .build();
6203 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6204 mCm.registerNetworkCallback(networkRequest, networkCallback);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006205
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006206 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006207 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006208 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006209 mCellNetworkAgent.connect(false);
paulhu66269b32019-08-30 19:24:36 +08006210 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006211 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6212
6213 // Change link Properties should have updated tcp buffer size.
6214 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006215 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006216 mCellNetworkAgent.sendLinkProperties(lp);
Chalard Jean059c4262019-09-30 17:51:12 +09006217 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006218 verifyTcpBufferSizeChange(testTcpBufferSizes);
paulhu66269b32019-08-30 19:24:36 +08006219
6220 // Clean up.
6221 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006222 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
paulhu66269b32019-08-30 19:24:36 +08006223 networkCallback.assertNoCallback();
6224 mCm.unregisterNetworkCallback(networkCallback);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006225 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006226
6227 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006228 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006229 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006230 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006231 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6232 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6233 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6234 }
6235
6236 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006237 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006238 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006239 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006240 mWiFiNetworkAgent.connect(true);
6241 waitForIdle();
6242 assertNull(mService.getProxyForNetwork(null));
6243
6244 final LinkProperties testLinkProperties = new LinkProperties();
6245 testLinkProperties.setHttpProxy(testProxyInfo);
6246
6247 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6248 waitForIdle();
6249
6250 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6251 }
6252
6253 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006254 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006255 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6256
6257 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006258 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006259 mWiFiNetworkAgent.connect(true);
6260 waitForIdle();
6261 assertNull(mService.getProxyForNetwork(null));
6262
6263 // Set up a VPN network with a proxy
6264 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006265 final TestNetworkAgentWrapper
6266 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006267 final ArraySet<UidRange> ranges = new ArraySet<>();
6268 ranges.add(new UidRange(uid, uid));
6269 mMockVpn.setUids(ranges);
6270 LinkProperties testLinkProperties = new LinkProperties();
6271 testLinkProperties.setHttpProxy(testProxyInfo);
6272 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6273 waitForIdle();
6274
6275 // Connect to VPN with proxy
6276 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6277 vpnNetworkAgent.connect(true);
6278 mMockVpn.connect();
6279 waitForIdle();
6280
6281 // Test that the VPN network returns a proxy, and the WiFi does not.
6282 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6283 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6284 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6285
6286 // Test that the VPN network returns no proxy when it is set to null.
6287 testLinkProperties.setHttpProxy(null);
6288 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6289 waitForIdle();
6290 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6291 assertNull(mService.getProxyForNetwork(null));
6292
6293 // Set WiFi proxy and check that the vpn proxy is still null.
6294 testLinkProperties.setHttpProxy(testProxyInfo);
6295 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6296 waitForIdle();
6297 assertNull(mService.getProxyForNetwork(null));
6298
6299 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6300 // correct proxy setting.
6301 vpnNetworkAgent.disconnect();
6302 waitForIdle();
6303 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6304 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6305 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6306 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006307
6308 @Test
6309 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6310 LinkProperties lp = new LinkProperties();
6311 lp.setInterfaceName("tun0");
6312 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6313 // The uid range needs to cover the test app so the network is visible to it.
6314 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006315 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006316
6317 // Connected VPN should have interface rules set up. There are two expected invocations,
6318 // one during VPN uid update, one during VPN LinkProperties update
6319 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6320 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6321 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6322 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6323 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6324
6325 vpnNetworkAgent.disconnect();
6326 waitForIdle();
6327
6328 // Disconnected VPN should have interface rules removed
6329 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6330 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6331 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6332 }
6333
6334 @Test
6335 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6336 LinkProperties lp = new LinkProperties();
6337 lp.setInterfaceName("tun0");
6338 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6339 // The uid range needs to cover the test app so the network is visible to it.
6340 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006341 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6342 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006343
6344 // Legacy VPN should not have interface rules set up
6345 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6346 }
6347
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09006348 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006349 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6350 throws Exception {
6351 LinkProperties lp = new LinkProperties();
6352 lp.setInterfaceName("tun0");
6353 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6354 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6355 // The uid range needs to cover the test app so the network is visible to it.
6356 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006357 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6358 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006359
6360 // IPv6 unreachable route should not be misinterpreted as a default route
6361 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6362 }
6363
6364 @Test
6365 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6366 LinkProperties lp = new LinkProperties();
6367 lp.setInterfaceName("tun0");
6368 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6369 // The uid range needs to cover the test app so the network is visible to it.
6370 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006371 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006372
6373 // Connected VPN should have interface rules set up. There are two expected invocations,
6374 // one during VPN uid update, one during VPN LinkProperties update
6375 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6376 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6377 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6378 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6379
6380 reset(mMockNetd);
6381 InOrder inOrder = inOrder(mMockNetd);
6382 lp.setInterfaceName("tun1");
6383 vpnNetworkAgent.sendLinkProperties(lp);
6384 waitForIdle();
6385 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6386 // removed first, then new rules added)
6387 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6388 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6389 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6390 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6391
6392 reset(mMockNetd);
6393 lp = new LinkProperties();
6394 lp.setInterfaceName("tun1");
6395 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6396 vpnNetworkAgent.sendLinkProperties(lp);
6397 waitForIdle();
6398 // VPN not routing everything should no longer have interface filtering rules
6399 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6400 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6401
6402 reset(mMockNetd);
6403 lp = new LinkProperties();
6404 lp.setInterfaceName("tun1");
6405 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6406 vpnNetworkAgent.sendLinkProperties(lp);
6407 waitForIdle();
6408 // Back to routing all IPv6 traffic should have filtering rules
6409 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6410 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6411 }
6412
6413 @Test
6414 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6415 LinkProperties lp = new LinkProperties();
6416 lp.setInterfaceName("tun0");
6417 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6418 // The uid range needs to cover the test app so the network is visible to it.
6419 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006420 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006421 Collections.singleton(vpnRange));
6422
6423 reset(mMockNetd);
6424 InOrder inOrder = inOrder(mMockNetd);
6425
6426 // Update to new range which is old range minus APP1, i.e. only APP2
6427 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6428 new UidRange(vpnRange.start, APP1_UID - 1),
6429 new UidRange(APP1_UID + 1, vpnRange.stop)));
6430 vpnNetworkAgent.setUids(newRanges);
6431 waitForIdle();
6432
6433 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6434 // Verify old rules are removed before new rules are added
6435 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6436 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6437 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6438 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6439 }
6440
Valentin Iftimec86ebba2019-09-24 13:32:13 +02006441 @Test
6442 public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
6443 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6444
6445 LinkProperties wifiLp = new LinkProperties();
6446 wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
6447 wifiLp.setWakeOnLanSupported(false);
6448
6449 // Default network switch should update ifaces.
6450 mWiFiNetworkAgent.connect(false);
6451 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6452 waitForIdle();
6453
6454 // ConnectivityService should have changed the WakeOnLanSupported to true
6455 wifiLp.setWakeOnLanSupported(true);
6456 assertEquals(wifiLp, mService.getActiveLinkProperties());
6457 }
6458
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006459 private void setupLocationPermissions(
6460 int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
6461 final ApplicationInfo applicationInfo = new ApplicationInfo();
6462 applicationInfo.targetSdkVersion = targetSdk;
6463 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
6464 .thenReturn(applicationInfo);
6465
6466 when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
6467
6468 if (op != null) {
6469 when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
6470 .thenReturn(AppOpsManager.MODE_ALLOWED);
6471 }
6472
6473 if (perm != null) {
6474 mServiceContext.setPermission(perm, PERMISSION_GRANTED);
6475 }
6476 }
6477
6478 private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
6479 final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
6480
6481 return mService
6482 .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
6483 .getOwnerUid();
6484 }
6485
Qingxi Li7cf06622020-01-17 17:54:27 -08006486 @Test
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006487 public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
6488 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6489 Manifest.permission.ACCESS_FINE_LOCATION);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006490
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006491 final int myUid = Process.myUid();
6492 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6493 }
Qingxi Li7cf06622020-01-17 17:54:27 -08006494
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006495 @Test
6496 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception {
6497 setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
6498 Manifest.permission.ACCESS_COARSE_LOCATION);
6499
6500 final int myUid = Process.myUid();
6501 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6502 }
6503
6504 @Test
6505 public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception {
6506 // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
6507 setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
6508 Manifest.permission.ACCESS_FINE_LOCATION);
6509
6510 final int myUid = Process.myUid();
6511 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6512 }
6513
6514 @Test
6515 public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception {
6516 // Test that even with fine location permission, not being the owner leads to sanitization.
6517 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6518 Manifest.permission.ACCESS_FINE_LOCATION);
6519
6520 final int myUid = Process.myUid();
6521 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
6522 }
6523
6524 @Test
6525 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception {
6526 // Test that not having fine location permission leads to sanitization.
6527 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
6528 Manifest.permission.ACCESS_COARSE_LOCATION);
6529
6530 // Test that without the location permission, the owner field is sanitized.
6531 final int myUid = Process.myUid();
6532 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6533 }
6534
6535 @Test
6536 public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception {
6537 setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
6538
6539 // Test that without the location permission, the owner field is sanitized.
6540 final int myUid = Process.myUid();
6541 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
Qingxi Li7cf06622020-01-17 17:54:27 -08006542 }
6543
Benedict Wong5d50ce82020-01-20 22:14:59 -08006544 private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
6545 throws Exception {
6546 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6547 establishVpn(new LinkProperties(), vpnOwnerUid, vpnRange);
6548 mMockVpn.setVpnType(vpnType);
6549
6550 final VpnInfo vpnInfo = new VpnInfo();
6551 vpnInfo.ownerUid = vpnOwnerUid;
6552 mMockVpn.setVpnInfo(vpnInfo);
6553 }
6554
6555 private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
6556 throws Exception {
6557 setupConnectionOwnerUid(vpnOwnerUid, vpnType);
6558
6559 // Test as VPN app
6560 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6561 mServiceContext.setPermission(
6562 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
6563 }
6564
6565 private ConnectionInfo getTestConnectionInfo() throws Exception {
6566 return new ConnectionInfo(
6567 IPPROTO_TCP,
6568 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
6569 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
6570 }
6571
6572 @Test
6573 public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
6574 final int myUid = Process.myUid();
6575 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
6576
6577 try {
6578 mService.getConnectionOwnerUid(getTestConnectionInfo());
6579 fail("Expected SecurityException for non-VpnService app");
6580 } catch (SecurityException expected) {
6581 }
6582 }
6583
6584 @Test
6585 public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
6586 final int myUid = Process.myUid();
6587 setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
6588
6589 try {
6590 mService.getConnectionOwnerUid(getTestConnectionInfo());
6591 fail("Expected SecurityException for non-VpnService app");
6592 } catch (SecurityException expected) {
6593 }
6594 }
6595
6596 @Test
6597 public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
6598 final int myUid = Process.myUid();
6599 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
6600
6601 // TODO: Test the returned UID
6602 mService.getConnectionOwnerUid(getTestConnectionInfo());
6603 }
6604
6605 @Test
6606 public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
6607 final int myUid = Process.myUid();
6608 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
6609 mServiceContext.setPermission(
6610 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6611
6612 // TODO: Test the returned UID
6613 mService.getConnectionOwnerUid(getTestConnectionInfo());
6614 }
6615
6616 @Test
6617 public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
6618 throws Exception {
6619 final int myUid = Process.myUid();
6620 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
6621 mServiceContext.setPermission(
6622 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
6623
6624 // TODO: Test the returned UID
6625 mService.getConnectionOwnerUid(getTestConnectionInfo());
6626 }
6627
Qingxi Li7cf06622020-01-17 17:54:27 -08006628 private TestNetworkAgentWrapper establishVpn(
6629 LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006630 final TestNetworkAgentWrapper
6631 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
Qingxi Li7cf06622020-01-17 17:54:27 -08006632 vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006633 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6634 mMockVpn.connect();
6635 mMockVpn.setUids(vpnRange);
6636 vpnNetworkAgent.connect(true);
6637 waitForIdle();
6638 return vpnNetworkAgent;
6639 }
6640
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006641 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6642 final PackageInfo packageInfo = new PackageInfo();
paulhu86e23eb2019-11-05 18:05:05 +08006643 if (hasSystemPermission) {
6644 packageInfo.requestedPermissions = new String[] {
6645 CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
6646 packageInfo.requestedPermissionsFlags = new int[] {
6647 REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
6648 } else {
6649 packageInfo.requestedPermissions = new String[0];
6650 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006651 packageInfo.applicationInfo = new ApplicationInfo();
6652 packageInfo.applicationInfo.privateFlags = 0;
6653 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6654 UserHandle.getAppId(uid));
6655 return packageInfo;
6656 }
Cody Kesting63e4e002019-12-18 10:57:50 -08006657
6658 @Test
6659 public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
6660 final NetworkRequest request =
6661 new NetworkRequest(
6662 new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
6663 try {
6664 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006665 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006666 fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
6667 } catch (IllegalArgumentException expected) {
6668 }
6669 }
6670
6671 @Test
6672 public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
6673 final NetworkRequest wifiRequest =
6674 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
Cody Kesting63e4e002019-12-18 10:57:50 -08006675 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6676
6677 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006678 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006679
Cody Kestinge330fcd2020-01-15 16:31:08 -08006680 // Block until all other events are done processing.
6681 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6682
6683 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
6684 verify(mConnectivityDiagnosticsCallback).asBinder();
Cody Kesting63e4e002019-12-18 10:57:50 -08006685 assertTrue(
6686 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6687 mConnectivityDiagnosticsCallback));
6688
6689 mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
6690 verify(mIBinder, timeout(TIMEOUT_MS))
6691 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
6692 assertFalse(
6693 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6694 mConnectivityDiagnosticsCallback));
6695 verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
6696 }
6697
6698 @Test
6699 public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
6700 final NetworkRequest wifiRequest =
6701 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
6702 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6703
6704 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006705 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006706
Cody Kestinge330fcd2020-01-15 16:31:08 -08006707 // Block until all other events are done processing.
6708 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6709
6710 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
Cody Kesting63e4e002019-12-18 10:57:50 -08006711 verify(mConnectivityDiagnosticsCallback).asBinder();
6712 assertTrue(
6713 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6714 mConnectivityDiagnosticsCallback));
6715
6716 // Register the same callback again
6717 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006718 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006719
6720 // Block until all other events are done processing.
6721 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6722
6723 assertTrue(
6724 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6725 mConnectivityDiagnosticsCallback));
6726 }
Cody Kestinga75e26b2020-01-05 14:06:39 -08006727
6728 @Test
6729 public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
6730 final NetworkAgentInfo naiWithoutUid =
6731 new NetworkAgentInfo(
6732 null, null, null, null, null, new NetworkCapabilities(), null,
6733 mServiceContext, null, null, mService, null, null, null, 0);
6734
6735 mServiceContext.setPermission(
6736 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6737 assertTrue(
6738 "NetworkStack permission not applied",
6739 mService.checkConnectivityDiagnosticsPermissions(
6740 Process.myPid(), Process.myUid(), naiWithoutUid,
6741 mContext.getOpPackageName()));
6742 }
6743
6744 @Test
6745 public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
6746 final NetworkAgentInfo naiWithoutUid =
6747 new NetworkAgentInfo(
6748 null, null, null, null, null, new NetworkCapabilities(), null,
6749 mServiceContext, null, null, mService, null, null, null, 0);
6750
6751 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6752
6753 assertFalse(
6754 "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics",
6755 mService.checkConnectivityDiagnosticsPermissions(
6756 Process.myPid(), Process.myUid(), naiWithoutUid,
6757 mContext.getOpPackageName()));
6758 }
6759
6760 @Test
6761 public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
6762 final NetworkAgentInfo naiWithoutUid =
6763 new NetworkAgentInfo(
6764 null, null, null, null, null, new NetworkCapabilities(), null,
6765 mServiceContext, null, null, mService, null, null, null, 0);
6766
6767 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6768 Manifest.permission.ACCESS_FINE_LOCATION);
6769 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6770
6771 // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be
6772 // active
6773 final VpnInfo info = new VpnInfo();
6774 info.ownerUid = Process.myUid();
6775 info.vpnIface = "interface";
6776 mMockVpn.setVpnInfo(info);
6777 assertTrue(
6778 "Active VPN permission not applied",
6779 mService.checkConnectivityDiagnosticsPermissions(
6780 Process.myPid(), Process.myUid(), naiWithoutUid,
6781 mContext.getOpPackageName()));
6782 }
6783
6784 @Test
6785 public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
6786 final NetworkCapabilities nc = new NetworkCapabilities();
6787 nc.setAdministratorUids(Arrays.asList(Process.myUid()));
6788 final NetworkAgentInfo naiWithUid =
6789 new NetworkAgentInfo(
6790 null, null, null, null, null, nc, null, mServiceContext, null, null,
6791 mService, null, null, null, 0);
6792
6793 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6794 Manifest.permission.ACCESS_FINE_LOCATION);
6795 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6796
6797 // Disconnect mock vpn so the uid check on NetworkAgentInfo is tested
6798 mMockVpn.disconnect();
6799 assertTrue(
6800 "NetworkCapabilities administrator uid permission not applied",
6801 mService.checkConnectivityDiagnosticsPermissions(
6802 Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
6803 }
6804
6805 @Test
6806 public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
6807 final NetworkCapabilities nc = new NetworkCapabilities();
6808 nc.setOwnerUid(Process.myUid());
6809 nc.setAdministratorUids(Arrays.asList(Process.myUid()));
6810 final NetworkAgentInfo naiWithUid =
6811 new NetworkAgentInfo(
6812 null, null, null, null, null, nc, null, mServiceContext, null, null,
6813 mService, null, null, null, 0);
6814
6815 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6816 Manifest.permission.ACCESS_FINE_LOCATION);
6817 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6818
6819 // Use wrong pid and uid
6820 assertFalse(
6821 "Permissions allowed when they shouldn't be granted",
6822 mService.checkConnectivityDiagnosticsPermissions(
6823 Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
6824 mContext.getOpPackageName()));
6825 }
6826
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006827 private void setUpConnectivityDiagnosticsCallback() throws Exception {
Cody Kestinga75e26b2020-01-05 14:06:39 -08006828 final NetworkRequest request = new NetworkRequest.Builder().build();
6829 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6830
6831 mServiceContext.setPermission(
6832 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6833
6834 mService.registerConnectivityDiagnosticsCallback(
6835 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
6836
6837 // Block until all other events are done processing.
6838 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6839
6840 // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
6841 final TestNetworkCallback callback = new TestNetworkCallback();
6842 mCm.registerDefaultNetworkCallback(callback);
6843 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6844 mCellNetworkAgent.connect(true);
6845 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6846 callback.assertNoCallback();
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006847 }
6848
6849 @Test
6850 public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception {
6851 setUpConnectivityDiagnosticsCallback();
Cody Kestinga75e26b2020-01-05 14:06:39 -08006852
Cody Kestinge330fcd2020-01-15 16:31:08 -08006853 // Block until all other events are done processing.
6854 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6855
6856 // Verify onConnectivityReport fired
6857 verify(mConnectivityDiagnosticsCallback)
Cody Kestinga75e26b2020-01-05 14:06:39 -08006858 .onConnectivityReport(any(ConnectivityReport.class));
6859 }
Cody Kesting4f49f142020-01-06 16:55:35 -08006860
6861 @Test
6862 public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006863 setUpConnectivityDiagnosticsCallback();
Cody Kesting4f49f142020-01-06 16:55:35 -08006864
6865 // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
6866 // cellular network agent
6867 mCellNetworkAgent.notifyDataStallSuspected();
6868
Cody Kestinge330fcd2020-01-15 16:31:08 -08006869 // Block until all other events are done processing.
6870 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6871
6872 // Verify onDataStallSuspected fired
6873 verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(any(DataStallReport.class));
Cody Kesting4f49f142020-01-06 16:55:35 -08006874 }
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006875
6876 @Test
6877 public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
6878 setUpConnectivityDiagnosticsCallback();
6879
6880 final Network n = mCellNetworkAgent.getNetwork();
6881 final boolean hasConnectivity = true;
6882 mService.reportNetworkConnectivity(n, hasConnectivity);
6883
Cody Kestinge330fcd2020-01-15 16:31:08 -08006884 // Block until all other events are done processing.
6885 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6886
6887 // Verify onNetworkConnectivityReported fired
6888 verify(mConnectivityDiagnosticsCallback)
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006889 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
6890
6891 final boolean noConnectivity = false;
6892 mService.reportNetworkConnectivity(n, noConnectivity);
6893
Cody Kestinge330fcd2020-01-15 16:31:08 -08006894 // Block until all other events are done processing.
6895 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6896
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006897 // Wait for onNetworkConnectivityReported to fire
Cody Kestinge330fcd2020-01-15 16:31:08 -08006898 verify(mConnectivityDiagnosticsCallback)
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006899 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
6900 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006901}