blob: c1999dba69032c657b5b75ca03abfec98801066b [file] [log] [blame]
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
paulhu86e23eb2019-11-05 18:05:05 +080019import static android.Manifest.permission.CHANGE_NETWORK_STATE;
20import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
21import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
Rubin Xu9e64dc02019-04-23 18:04:14 +010022import static android.content.pm.PackageManager.GET_PERMISSIONS;
23import static android.content.pm.PackageManager.MATCH_ANY_USER;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +090024import static android.content.pm.PackageManager.PERMISSION_DENIED;
25import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090026import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
Erik Klinef851d6d2015-04-20 16:03:48 +090027import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
Chalard Jean9ca13772019-11-15 12:08:36 +090028import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
29import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
30import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
Lorenzo Colittif56ff042019-02-25 10:56:06 +090031import static android.net.ConnectivityManager.NETID_UNSET;
Erik Kline79c6d052018-03-21 07:18:33 -070032import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
33import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
34import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +090035import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070036import static android.net.ConnectivityManager.TYPE_MOBILE;
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +090037import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
38import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
Chalard Jean9ca13772019-11-15 12:08:36 +090039import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -070040import static android.net.ConnectivityManager.TYPE_WIFI;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080041import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
42import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
43import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
44import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
lucaslin783f2212019-10-22 18:27:33 +080045import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
Chiachang Wang8ea15c962019-05-23 16:29:30 +080046import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
47import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060048import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
49import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
50import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
51import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
52import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
53import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
54import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
55import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
56import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
57import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
58import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
59import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
Chalard Jean804b8fb2018-01-30 22:41:41 +090060import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060061import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
lucasline252a742019-03-12 13:08:03 +080062import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060063import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
64import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
65import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
66import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
67import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
68import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
69import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
70import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
Chalard Jean0b214af2018-01-12 17:22:49 +090071import static android.net.NetworkCapabilities.TRANSPORT_VPN;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060072import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
73import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
Mike Yuf9729752018-08-17 15:22:05 +080074import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
75import static android.net.NetworkPolicyManager.RULE_NONE;
76import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
77import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +000078import static android.net.RouteInfo.RTN_UNREACHABLE;
Benedict Wong5d50ce82020-01-20 22:14:59 -080079import static android.system.OsConstants.IPPROTO_TCP;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060080
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090081import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090082import static com.android.testutils.ConcurrentUtilsKt.await;
83import static com.android.testutils.ConcurrentUtilsKt.durationOf;
Chalard Jeane7b24752019-06-20 16:01:19 +090084import static com.android.testutils.ExceptionUtils.ignoreExceptions;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090085import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
86import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
87import static com.android.testutils.MiscAssertsKt.assertEmpty;
88import static com.android.testutils.MiscAssertsKt.assertLength;
89import static com.android.testutils.MiscAssertsKt.assertRunsInAtMost;
90import static com.android.testutils.MiscAssertsKt.assertThrows;
91
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090092import static org.junit.Assert.assertEquals;
93import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080094import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090095import static org.junit.Assert.assertNotNull;
96import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060097import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090098import static org.junit.Assert.fail;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090099import static org.mockito.ArgumentMatchers.anyLong;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900100import static org.mockito.ArgumentMatchers.anyString;
Cody Kestinga3b71c42020-02-11 10:03:26 -0800101import static org.mockito.ArgumentMatchers.argThat;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000102import static org.mockito.ArgumentMatchers.eq;
Chalard Jean587758b2019-11-29 16:41:50 +0900103import static org.mockito.ArgumentMatchers.startsWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900104import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +0900105import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600106import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900107import static org.mockito.Mockito.doAnswer;
108import static org.mockito.Mockito.doNothing;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900109import static org.mockito.Mockito.doReturn;
Roshan Piuse38acab2020-01-16 12:17:17 -0800110import static org.mockito.Mockito.doThrow;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000111import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -0800112import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600113import static org.mockito.Mockito.never;
114import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900115import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900116import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +0900117import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600118import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -0700119import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900120import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700121
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900122import android.Manifest;
junyulai7c469172019-01-16 20:23:34 +0800123import android.annotation.NonNull;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900124import android.app.AlarmManager;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800125import android.app.AppOpsManager;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900126import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400127import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400128import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900129import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900130import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700131import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400132import android.content.Intent;
133import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000134import android.content.pm.ApplicationInfo;
135import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100136import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000137import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900138import android.content.res.Resources;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800139import android.location.LocationManager;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900140import android.net.CaptivePortalData;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800141import android.net.ConnectionInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400142import android.net.ConnectivityManager;
143import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900144import android.net.ConnectivityManager.PacketKeepalive;
145import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900146import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900147import android.net.ConnectivityThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800148import android.net.IConnectivityDiagnosticsCallback;
Luke Huang65914772019-03-16 00:31:46 +0800149import android.net.IDnsResolver;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900150import android.net.IIpConnectivityMetrics;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800151import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900152import android.net.INetworkMonitor;
153import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800154import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700155import android.net.INetworkPolicyManager;
156import android.net.INetworkStatsService;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800157import android.net.InetAddresses;
junyulai4a192e22018-06-13 15:00:37 +0800158import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900159import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800160import android.net.IpSecManager;
161import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900162import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700163import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700164import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400165import android.net.Network;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400166import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700167import android.net.NetworkFactory;
Chalard Jean9ca13772019-11-15 12:08:36 +0900168import android.net.NetworkInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400169import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700170import android.net.NetworkSpecifier;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900171import android.net.NetworkStack;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900172import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800173import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100174import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000175import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800176import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700177import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800178import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900179import android.net.UidRange;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900180import android.net.Uri;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800181import android.net.VpnManager;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900182import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900183import android.net.shared.NetworkMonitorUtils;
184import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900185import android.net.util.MultinetworkPolicyTracker;
Chalard Jean751bb3f2019-06-19 23:29:58 +0900186import android.os.BadParcelableException;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100187import android.os.Binder;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800188import android.os.Build;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900189import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400190import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700191import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700192import android.os.HandlerThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800193import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700194import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900195import android.os.Looper;
Etan Cohena7434272017-04-03 12:17:51 -0700196import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800197import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700198import android.os.Parcelable;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800199import android.os.PersistableBundle;
Robin Leed2baf792016-03-24 12:07:00 +0000200import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800201import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900202import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900203import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000204import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900205import android.provider.Settings;
Benedict Wongb570e862020-01-17 19:33:55 -0800206import android.security.KeyStore;
junyulai0c666972019-03-04 22:45:36 +0800207import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900208import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800209import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100210import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700211import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800212import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700213
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800214import androidx.test.InstrumentationRegistry;
Guang Zhub90866d2019-09-01 21:37:04 -0700215import androidx.test.filters.FlakyTest;
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800216import androidx.test.filters.SmallTest;
217import androidx.test.runner.AndroidJUnit4;
218
Chalard Jean587758b2019-11-29 16:41:50 +0900219import com.android.internal.app.IBatteryStats;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900220import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800221import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900222import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900223import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900224import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900225import com.android.internal.util.test.FakeSettingsProvider;
Cody Kesting63e4e002019-12-18 10:57:50 -0800226import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
Chalard Jeandda156a2018-01-10 21:19:32 +0900227import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900228import com.android.server.connectivity.DefaultNetworkMetrics;
229import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900230import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800231import com.android.server.connectivity.Nat464Xlat;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800232import com.android.server.connectivity.NetworkAgentInfo;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900233import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000234import com.android.server.connectivity.ProxyTracker;
Chalard Jeandda156a2018-01-10 21:19:32 +0900235import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900236import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900237import com.android.server.net.NetworkPolicyManagerInternal;
Chalard Jeane7b24752019-06-20 16:01:19 +0900238import com.android.testutils.ExceptionUtils;
Chalard Jeance75e0e2019-05-28 16:48:32 +0900239import com.android.testutils.HandlerUtilsKt;
Chalard Jean059c4262019-09-30 17:51:12 +0900240import com.android.testutils.RecorderCallback.CallbackEntry;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900241import com.android.testutils.TestableNetworkCallback;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400242
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900243import org.junit.After;
244import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900245import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900246import org.junit.Test;
247import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900248import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000249import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900250import org.mockito.Mock;
251import org.mockito.MockitoAnnotations;
252import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900253import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900254
junyulai0c666972019-03-04 22:45:36 +0800255import java.io.IOException;
256import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800257import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000258import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700259import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900260import java.net.InetSocketAddress;
261import java.net.Socket;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400262import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900263import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100264import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800265import java.util.Collections;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900266import java.util.HashMap;
dalyk1fcb7392018-03-05 12:42:22 -0500267import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100268import java.util.List;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900269import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100270import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900271import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800272import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800273import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800274import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900275import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900276import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700277import java.util.concurrent.atomic.AtomicBoolean;
Chalard Jean9ca13772019-11-15 12:08:36 +0900278import java.util.function.Predicate;
Benedict Wong5d50ce82020-01-20 22:14:59 -0800279import java.util.function.Supplier;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900280
281import kotlin.reflect.KClass;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700282
283/**
284 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400285 *
286 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900287 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700288 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900289@RunWith(AndroidJUnit4.class)
290@SmallTest
291public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700292 private static final String TAG = "ConnectivityServiceTest";
293
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900294 private static final int TIMEOUT_MS = 500;
Chalard Jeanb299b842019-09-27 17:13:14 +0900295 private static final int TEST_LINGER_DELAY_MS = 300;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900296 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
297 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
298 // timeout. For this, our assertions should run fast enough to leave less than
299 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
300 // supposedly fired, and the time we call expectCallback.
Chalard Jeanb299b842019-09-27 17:13:14 +0900301 private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900302 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
303 // complete before callbacks are verified.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900304 private static final int TEST_REQUEST_TIMEOUT_MS = 150;
305
306 private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900307
Cody Kestinga75e26b2020-01-05 14:06:39 -0800308 private static final long TIMESTAMP = 1234L;
309
junyulai4a192e22018-06-13 15:00:37 +0800310 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700311 private static final String MOBILE_IFNAME = "test_rmnet_data0";
312 private static final String WIFI_IFNAME = "test_wlan0";
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200313 private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
Roshan Piuse38acab2020-01-16 12:17:17 -0800314 private static final String TEST_PACKAGE_NAME = "com.android.test.package";
Luke Huang65914772019-03-16 00:31:46 +0800315 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700316
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900317 private MockContext mServiceContext;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900318 private HandlerThread mCsHandlerThread;
319 private ConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900320 private WrappedConnectivityManager mCm;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900321 private TestNetworkAgentWrapper mWiFiNetworkAgent;
322 private TestNetworkAgentWrapper mCellNetworkAgent;
323 private TestNetworkAgentWrapper mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900324 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900325 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800326 private INetworkPolicyListener mPolicyListener;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900327 private WrappedMultinetworkPolicyTracker mPolicyTracker;
328 private HandlerThread mAlarmManagerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700329
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900330 @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
Hugo Benichi64901e52017-10-19 14:42:40 +0900331 @Mock IpConnectivityMetrics.Logger mMetricsService;
332 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900333 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600334 @Mock INetworkStatsService mStatsService;
Chalard Jean587758b2019-11-29 16:41:50 +0900335 @Mock IBatteryStats mBatteryStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800336 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800337 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800338 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900339 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100340 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000341 @Mock UserManager mUserManager;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900342 @Mock NotificationManager mNotificationManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900343 @Mock AlarmManager mAlarmManager;
Cody Kesting63e4e002019-12-18 10:57:50 -0800344 @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
345 @Mock IBinder mIBinder;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800346 @Mock LocationManager mLocationManager;
347 @Mock AppOpsManager mAppOpsManager;
Hugo Benichi64901e52017-10-19 14:42:40 +0900348
waynema13516842019-03-12 18:13:49 +0800349 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
350 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900351
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900352 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
353 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
354 // reflect the state of our test ConnectivityService.
355 private class WrappedConnectivityManager extends ConnectivityManager {
356 private Network mFakeBoundNetwork;
357
358 public synchronized boolean bindProcessToNetwork(Network network) {
359 mFakeBoundNetwork = network;
360 return true;
361 }
362
363 public synchronized Network getBoundNetworkForProcess() {
364 return mFakeBoundNetwork;
365 }
366
367 public WrappedConnectivityManager(Context context, ConnectivityService service) {
368 super(context, service);
369 }
370 }
371
Paul Jensend7b6ca92015-05-13 14:05:12 -0400372 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900373 private final MockContentResolver mContentResolver;
Chalard Jean9ca13772019-11-15 12:08:36 +0900374 // Contains all registered receivers since this object was created. Useful to clear
375 // them when needed, as BroadcastInterceptingContext does not provide this facility.
376 private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>();
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900377
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900378 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900379 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900380 // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
381 private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900382
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900383 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400384 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900385
386 mResources = spy(base.getResources());
387 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
388 thenReturn(new String[] {
389 "wifi,1,1,1,-1,true",
390 "mobile,0,0,0,-1,true",
391 "mobile_mms,2,0,2,60000,true",
Chalard Jean9ca13772019-11-15 12:08:36 +0900392 "mobile_supl,3,0,2,60000,true",
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900393 });
394
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200395 when(mResources.getStringArray(
396 com.android.internal.R.array.config_wakeonlan_supported_interfaces))
397 .thenReturn(new String[]{
398 WIFI_WOL_IFNAME,
399 });
400
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900401 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900402 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400403 }
404
405 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900406 public void startActivityAsUser(Intent intent, UserHandle handle) {
407 mStartedActivities.offer(intent);
408 }
409
Chalard Jeanf30d1e12019-06-27 08:24:51 +0000410 public Intent expectStartActivityIntent(int timeoutMs) {
411 Intent intent = null;
412 try {
413 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
414 } catch (InterruptedException e) {}
415 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
416 return intent;
417 }
418
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900419 public void expectNoStartActivityIntent(int timeoutMs) {
420 try {
421 assertNull("Received unexpected Intent to start activity",
422 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
423 } catch (InterruptedException e) {}
424 }
425
426 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900427 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900428 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900429 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900430 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000431 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900432 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800433 if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
434 if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400435 return super.getSystemService(name);
436 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900437
438 @Override
439 public ContentResolver getContentResolver() {
440 return mContentResolver;
441 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900442
443 @Override
444 public Resources getResources() {
445 return mResources;
446 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100447
448 @Override
449 public PackageManager getPackageManager() {
450 return mPackageManager;
451 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900452
Benedict Wong5d50ce82020-01-20 22:14:59 -0800453 private int checkMockedPermission(String permission, Supplier<Integer> ifAbsent) {
454 final Integer granted = mMockedPermissions.get(permission);
455 return granted != null ? granted : ifAbsent.get();
456 }
457
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900458 @Override
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900459 public int checkPermission(String permission, int pid, int uid) {
Benedict Wong5d50ce82020-01-20 22:14:59 -0800460 return checkMockedPermission(
461 permission, () -> super.checkPermission(permission, pid, uid));
462 }
463
464 @Override
465 public int checkCallingOrSelfPermission(String permission) {
466 return checkMockedPermission(
467 permission, () -> super.checkCallingOrSelfPermission(permission));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900468 }
469
470 @Override
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900471 public void enforceCallingOrSelfPermission(String permission, String message) {
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900472 final Integer granted = mMockedPermissions.get(permission);
473 if (granted == null) {
474 super.enforceCallingOrSelfPermission(permission, message);
475 return;
476 }
477
478 if (!granted.equals(PERMISSION_GRANTED)) {
479 throw new SecurityException("[Test] permission denied: " + permission);
480 }
481 }
482
483 /**
484 * Mock checks for the specified permission, and have them behave as per {@code granted}.
485 *
486 * <p>Passing null reverts to default behavior, which does a real permission check on the
487 * test package.
488 * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
489 * {@link PackageManager#PERMISSION_DENIED}.
490 */
491 public void setPermission(String permission, Integer granted) {
492 mMockedPermissions.put(permission, granted);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900493 }
Chalard Jean9ca13772019-11-15 12:08:36 +0900494
495 @Override
496 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
497 mRegisteredReceivers.add(receiver);
498 return super.registerReceiver(receiver, filter);
499 }
500
501 public void clearRegisteredReceivers() {
502 // super.unregisterReceiver is a no-op for receivers that are not registered (because
503 // they haven't been registered or because they have already been unregistered).
504 // For the same reason, don't bother clearing mRegisteredReceivers.
505 for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv);
506 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900507 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400508
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900509 private void waitForIdle() {
510 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
511 waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
512 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
513 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
514 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
515 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Hugo Benichibb91c572017-05-22 10:44:02 +0900516 }
517
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900518 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900519 if (agent == null) {
520 return;
521 }
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900522 agent.waitForIdle(timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900523 }
524
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900525 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +0900526 public void testWaitForIdle() throws Exception {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900527 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
528
529 // Tests that waitForIdle returns immediately if the service is already idle.
530 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900531 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900532 }
533
534 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900535 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900536 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900537 mWiFiNetworkAgent.connect(false);
538 waitFor(cv);
539 Network n = mWiFiNetworkAgent.getNetwork();
540 assertNotNull(n);
541
542 // Tests that calling waitForIdle waits for messages to be processed.
543 for (int i = 0; i < attempts; i++) {
544 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900545 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900546 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
547 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900548 }
549
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900550 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
551 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800552 @Ignore
Chalard Jeane7b24752019-06-20 16:01:19 +0900553 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900554 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900555 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900556 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Hugo Benichi5d540d12016-10-17 15:54:51 +0900557 mWiFiNetworkAgent.connect(false);
558 waitFor(cv);
559 Network n = mWiFiNetworkAgent.getNetwork();
560 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900561
562 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900563 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900564 for (int i = 0; i < attempts; i++) {
565 mWiFiNetworkAgent.setSignalStrength(i);
566 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
567 // We hit a race condition, as expected. Pass the test.
568 return;
569 }
570 }
571
572 // No race? There is a bug in this test.
573 fail("expected race condition at least once in " + attempts + " attempts");
574 }
575
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900576 private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800577 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
578 | NETWORK_VALIDATION_PROBE_HTTP
579 | NETWORK_VALIDATION_PROBE_HTTPS;
580 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
581 | NETWORK_VALIDATION_RESULT_VALID;
582 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
583 | NETWORK_VALIDATION_PROBE_FALLBACK
584 | NETWORK_VALIDATION_RESULT_PARTIAL;
585 private static final int VALIDATION_RESULT_INVALID = 0;
586
Cody Kesting4f49f142020-01-06 16:55:35 -0800587 private static final long DATA_STALL_TIMESTAMP = 10L;
588 private static final int DATA_STALL_DETECTION_METHOD = 1;
589
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900590 private INetworkMonitor mNetworkMonitor;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900591 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800592 private int mNmValidationResult = VALIDATION_RESULT_BASE;
lucaslin783f2212019-10-22 18:27:33 +0800593 private int mProbesCompleted;
594 private int mProbesSucceeded;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900595 private String mNmValidationRedirectUrl = null;
Cody Kestinga75e26b2020-01-05 14:06:39 -0800596 private PersistableBundle mValidationExtras = PersistableBundle.EMPTY;
Cody Kesting4f49f142020-01-06 16:55:35 -0800597 private PersistableBundle mDataStallExtras = PersistableBundle.EMPTY;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900598 private boolean mNmProvNotificationRequested = false;
599
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900600 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
601 // Contains the redirectUrl from networkStatus(). Before reading, wait for
602 // mNetworkStatusReceived.
603 private String mRedirectUrl;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900604
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900605 TestNetworkAgentWrapper(int transport) throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100606 this(transport, new LinkProperties());
607 }
608
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900609 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
610 throws Exception {
611 super(transport, linkProperties, mServiceContext);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900612
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900613 // Waits for the NetworkAgent to be registered, which includes the creation of the
614 // NetworkMonitor.
615 waitForIdle(TIMEOUT_MS);
Chalard Jean3da8e0f2019-09-20 17:19:31 +0900616 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
617 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900618 }
619
620 @Override
621 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
622 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900623 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900624
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900625 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900626 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900627 return null;
628 };
629
Chalard Jeane7b24752019-06-20 16:01:19 +0900630 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
631 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900632
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900633 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900634 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
635 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
636 doNothing().when(mNetworkStack).makeNetworkMonitor(
637 nmNetworkCaptor.capture(),
638 any() /* name */,
639 nmCbCaptor.capture());
640
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900641 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400642 @Override
643 public void networkStatus(int status, String redirectUrl) {
644 mRedirectUrl = redirectUrl;
645 mNetworkStatusReceived.open();
646 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400647 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900648
Chalard Jean29c6e0c2020-01-16 17:13:26 +0900649 assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900650 mNmCallbacks = nmCbCaptor.getValue();
651
Chalard Jeane7b24752019-06-20 16:01:19 +0900652 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900653
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900654 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900655 }
656
Chalard Jeane7b24752019-06-20 16:01:19 +0900657 private void onValidationRequested() throws Exception {
658 if (mNmProvNotificationRequested
659 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
660 mNmCallbacks.hideProvisioningNotification();
661 mNmProvNotificationRequested = false;
662 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900663
lucaslin783f2212019-10-22 18:27:33 +0800664 mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
Cody Kestinga75e26b2020-01-05 14:06:39 -0800665 mNmCallbacks.notifyNetworkTestedWithExtras(
666 mNmValidationResult, mNmValidationRedirectUrl, TIMESTAMP, mValidationExtras);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900667
Chalard Jeane7b24752019-06-20 16:01:19 +0900668 if (mNmValidationRedirectUrl != null) {
669 mNmCallbacks.showProvisioningNotification(
Roshan Piuse38acab2020-01-16 12:17:17 -0800670 "test_provisioning_notif_action", TEST_PACKAGE_NAME);
Chalard Jeane7b24752019-06-20 16:01:19 +0900671 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900672 }
Paul Jensen3d911462015-06-12 06:40:24 -0400673 }
674
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900675 /**
676 * Connect without adding any internet capability.
677 */
Paul Jensene0988542015-06-25 15:30:08 -0400678 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900679 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400680 }
681
Paul Jensend7b6ca92015-05-13 14:05:12 -0400682 /**
Paul Jensene0988542015-06-25 15:30:08 -0400683 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400684 * @param validated Indicate if network should pretend to be validated.
685 */
686 public void connect(boolean validated) {
lucaslin783f2212019-10-22 18:27:33 +0800687 connect(validated, true, false /* isStrictMode */);
Hugo Benichi16f0a942017-06-20 14:07:59 +0900688 }
689
690 /**
691 * Transition this NetworkAgent to CONNECTED state.
692 * @param validated Indicate if network should pretend to be validated.
693 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
694 */
lucaslin783f2212019-10-22 18:27:33 +0800695 public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900696 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400697
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900698 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400699 final ConditionVariable validatedCv = new ConditionVariable();
700 if (validated) {
lucaslin783f2212019-10-22 18:27:33 +0800701 setNetworkValid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400702 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900703 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900704 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400705 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900706 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400707 public void onCapabilitiesChanged(Network network,
708 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400709 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900710 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400711 validatedCv.open();
712 }
713 }
714 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400715 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400716 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900717 if (hasInternet) {
718 addCapability(NET_CAPABILITY_INTERNET);
719 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400720
Paul Jensene0988542015-06-25 15:30:08 -0400721 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400722
723 if (validated) {
724 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400725 waitFor(validatedCv);
lucaslin783f2212019-10-22 18:27:33 +0800726 setNetworkInvalid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400727 }
728
729 if (callback != null) mCm.unregisterNetworkCallback(callback);
730 }
731
lucaslin783f2212019-10-22 18:27:33 +0800732 public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
733 setNetworkPortal(redirectUrl, isStrictMode);
734 connect(false, true /* hasInternet */, isStrictMode);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400735 }
736
lucasline252a742019-03-12 13:08:03 +0800737 public void connectWithPartialConnectivity() {
738 setNetworkPartial();
739 connect(false);
740 }
741
lucaslin783f2212019-10-22 18:27:33 +0800742 public void connectWithPartialValidConnectivity(boolean isStrictMode) {
743 setNetworkPartialValid(isStrictMode);
744 connect(false, true /* hasInternet */, isStrictMode);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900745 }
746
lucaslin783f2212019-10-22 18:27:33 +0800747 void setNetworkValid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900748 mNmValidationResult = VALIDATION_RESULT_VALID;
749 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800750 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP;
751 if (isStrictMode) {
752 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
753 }
754 // The probesCompleted equals to probesSucceeded for the case of valid network, so put
755 // the same value into two different parameter of the method.
756 setProbesStatus(probesSucceeded, probesSucceeded);
Erik Kline1d3db322017-02-28 16:20:20 +0900757 }
758
lucaslin783f2212019-10-22 18:27:33 +0800759 void setNetworkInvalid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900760 mNmValidationResult = VALIDATION_RESULT_INVALID;
761 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800762 int probesCompleted = VALIDATION_RESULT_BASE;
763 int probesSucceeded = VALIDATION_RESULT_INVALID;
764 // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
765 // tried to validate the private DNS but failed.
766 if (isStrictMode) {
767 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
768 probesSucceeded = probesCompleted;
769 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
770 }
771 setProbesStatus(probesCompleted, probesSucceeded);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900772 }
773
lucaslin783f2212019-10-22 18:27:33 +0800774 void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
775 setNetworkInvalid(isStrictMode);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900776 mNmValidationRedirectUrl = redirectUrl;
lucaslin783f2212019-10-22 18:27:33 +0800777 // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
778 // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
779 int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
780 int probesSucceeded = VALIDATION_RESULT_INVALID;
781 if (isStrictMode) {
782 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
783 }
784 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400785 }
786
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900787 void setNetworkPartial() {
788 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
789 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800790 int probesCompleted = VALIDATION_RESULT_BASE;
791 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
792 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400793 }
Paul Jensene0988542015-06-25 15:30:08 -0400794
lucaslin783f2212019-10-22 18:27:33 +0800795 void setNetworkPartialValid(boolean isStrictMode) {
796 setNetworkPartial();
797 mNmValidationResult |= VALIDATION_RESULT_VALID;
798 int probesCompleted = VALIDATION_RESULT_BASE;
799 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
800 // Suppose the partial network cannot pass the private DNS validation as well, so only
801 // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
802 if (isStrictMode) {
803 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
804 }
805 setProbesStatus(probesCompleted, probesSucceeded);
806 }
807
808 void setProbesStatus(int probesCompleted, int probesSucceeded) {
809 mProbesCompleted = probesCompleted;
810 mProbesSucceeded = probesSucceeded;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900811 }
Paul Jensen232437312016-04-06 09:51:26 -0400812
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +0900813 void notifyCaptivePortalDataChanged(CaptivePortalData data) {
814 try {
815 mNmCallbacks.notifyCaptivePortalDataChanged(data);
816 } catch (RemoteException e) {
817 throw new AssertionError("This cannot happen", e);
818 }
819 }
820
Paul Jensen232437312016-04-06 09:51:26 -0400821 public String waitForRedirectUrl() {
822 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
823 return mRedirectUrl;
824 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900825
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900826 public void expectDisconnected() {
827 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900828 }
829
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900830 public void expectPreventReconnectReceived() {
831 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900832 }
Cody Kesting4f49f142020-01-06 16:55:35 -0800833
834 void notifyDataStallSuspected() throws Exception {
835 mNmCallbacks.notifyDataStallSuspected(
836 DATA_STALL_TIMESTAMP, DATA_STALL_DETECTION_METHOD, mDataStallExtras);
837 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400838 }
839
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900840 /**
841 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
842 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900843 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900844 * expectRemoveRequests.
845 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700846 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400847 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
848 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400849 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700850
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900851 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900852 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
853 // once, then cause some other thread to add or remove requests, then call
854 // waitForRequests().
855 // It is not possible to wait for both add and remove requests. When adding, the queue
856 // contains the expected score. When removing, the value is unused, all matters is the
857 // number of objects in the queue.
858 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900859
860 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900861 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900862 private boolean mExpectingAdditions;
863
Etan Cohenddb720a2019-01-08 12:09:18 -0800864 // Used to collect the networks requests managed by this factory. This is a duplicate of
865 // the internal information stored in the NetworkFactory (which is private).
866 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
867
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700868 public MockNetworkFactory(Looper looper, Context context, String logTag,
869 NetworkCapabilities filter) {
870 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900871 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700872 }
873
874 public int getMyRequestCount() {
875 return getRequestCount();
876 }
877
878 protected void startNetwork() {
879 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400880 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700881 }
882
883 protected void stopNetwork() {
884 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400885 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700886 }
887
888 public boolean getMyStartRequested() {
889 return mNetworkStarted.get();
890 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400891
892 public ConditionVariable getNetworkStartedCV() {
893 mNetworkStartedCV.close();
894 return mNetworkStartedCV;
895 }
896
897 public ConditionVariable getNetworkStoppedCV() {
898 mNetworkStoppedCV.close();
899 return mNetworkStoppedCV;
900 }
901
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900902 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900903 protected void handleAddRequest(NetworkRequest request, int score,
904 int factorySerialNumber) {
905 synchronized (mExpectations) {
906 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900907
Chalard Jean05ab6812018-05-02 21:14:54 +0900908 assertNotNull("Added more requests than expected (" + request + " score : "
909 + score + ")", expectedScore);
910 // If we're expecting anything, we must be expecting additions.
911 if (!mExpectingAdditions) {
912 fail("Can't add requests while expecting requests to be removed");
913 }
914 if (expectedScore != score) {
915 fail("Expected score was " + expectedScore + " but actual was " + score
916 + " in added request");
917 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900918
Chalard Jean05ab6812018-05-02 21:14:54 +0900919 // Add the request.
920 mNetworkRequests.put(request.requestId, request);
921 super.handleAddRequest(request, score, factorySerialNumber);
922 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900923 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400924 }
925
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900926 @Override
927 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900928 synchronized (mExpectations) {
929 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900930
Chalard Jean05ab6812018-05-02 21:14:54 +0900931 assertTrue("Removed more requests than expected", expectedScore != null);
932 // If we're expecting anything, we must be expecting removals.
933 if (mExpectingAdditions) {
934 fail("Can't remove requests while expecting requests to be added");
935 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900936
Chalard Jean05ab6812018-05-02 21:14:54 +0900937 // Remove the request.
938 mNetworkRequests.remove(request.requestId);
939 super.handleRemoveRequest(request);
940 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900941 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400942 }
943
Etan Cohenddb720a2019-01-08 12:09:18 -0800944 // Trigger releasing the request as unfulfillable
945 public void triggerUnfulfillable(NetworkRequest r) {
946 super.releaseRequestAsUnfulfillableByAnyFactory(r);
947 }
948
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900949 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900950 if (mExpectations.size() != 0) {
951 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900952 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400953 }
954
Chalard Jean05ab6812018-05-02 21:14:54 +0900955 // Expects that requests with the specified scores will be added.
956 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900957 assertNoExpectations();
958 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900959 for (int score : scores) {
960 mExpectations.add(score);
961 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400962 }
963
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900964 // Expects that count requests will be removed.
965 public void expectRemoveRequests(final int count) {
966 assertNoExpectations();
967 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900968 for (int i = 0; i < count; ++i) {
969 mExpectations.add(0); // For removals the score is ignored so any value will do.
970 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900971 }
972
973 // Waits for the expected request additions or removals to happen within a timeout.
974 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900975 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
976 synchronized (mExpectations) {
977 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
978 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
979 }
980 }
981 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900982 final String msg = count + " requests still not " +
983 (mExpectingAdditions ? "added" : "removed") +
984 " after " + TIMEOUT_MS + " ms";
985 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900986 }
987
Etan Cohenddb720a2019-01-08 12:09:18 -0800988 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
989 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900990 waitForRequests();
991 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800992 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400993 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700994 }
995
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900996 private static Looper startHandlerThreadAndReturnLooper() {
997 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
998 handlerThread.start();
999 return handlerThread.getLooper();
1000 }
1001
1002 private class MockVpn extends Vpn {
1003 // TODO : the interactions between this mock and the mock network agent are too
1004 // hard to get right at this moment, because it's unclear in which case which
1005 // target needs to get a method call or both, and in what order. It's because
1006 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
1007 // parent class of MockVpn agent wants that responsibility.
1008 // That being said inside the test it should be possible to make the interactions
1009 // harder to get wrong with precise speccing, judicious comments, helper methods
1010 // and a few sprinkled assertions.
1011
1012 private boolean mConnected = false;
1013 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
1014 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001015 private TestNetworkAgentWrapper mMockNetworkAgent;
Benedict Wong5d50ce82020-01-20 22:14:59 -08001016 private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001017
Cody Kestinga75e26b2020-01-05 14:06:39 -08001018 private VpnInfo mVpnInfo;
1019
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001020 public MockVpn(int userId) {
1021 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
Benedict Wongb570e862020-01-17 19:33:55 -08001022 userId, mock(KeyStore.class));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001023 }
1024
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001025 public void setNetworkAgent(TestNetworkAgentWrapper agent) {
1026 agent.waitForIdle(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001027 mMockNetworkAgent = agent;
1028 mNetworkAgent = agent.getNetworkAgent();
1029 mNetworkCapabilities.set(agent.getNetworkCapabilities());
1030 }
1031
1032 public void setUids(Set<UidRange> uids) {
1033 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -08001034 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001035 }
1036
Benedict Wong5d50ce82020-01-20 22:14:59 -08001037 public void setVpnType(int vpnType) {
1038 mVpnType = vpnType;
1039 }
1040
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001041 @Override
1042 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -08001043 if (mMockNetworkAgent == null) {
1044 return NETID_UNSET;
1045 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001046 return mMockNetworkAgent.getNetwork().netId;
1047 }
1048
1049 @Override
1050 public boolean appliesToUid(int uid) {
1051 return mConnected; // Trickery to simplify testing.
1052 }
1053
1054 @Override
1055 protected boolean isCallerEstablishedOwnerLocked() {
1056 return mConnected; // Similar trickery
1057 }
1058
Benedict Wong5d50ce82020-01-20 22:14:59 -08001059 @Override
1060 public int getActiveAppVpnType() {
1061 return mVpnType;
1062 }
1063
Varun Anandc51b06d2019-02-25 17:22:02 -08001064 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001065 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1066 mConnected = true;
1067 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -08001068 mConfig.isMetered = isAlwaysMetered;
1069 }
1070
1071 public void connectAsAlwaysMetered() {
1072 connect(true /* isAlwaysMetered */);
1073 }
1074
1075 public void connect() {
1076 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001077 }
1078
1079 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001080 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1081 if (!mConnected) return null;
1082 super.updateCapabilities(defaultNetwork);
1083 // Because super.updateCapabilities will update the capabilities of the agent but
1084 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001085 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -08001086 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001087 }
1088
1089 private void copyCapabilitiesToNetworkAgent() {
1090 if (null != mMockNetworkAgent) {
1091 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1092 false /* sendToConnectivityService */);
1093 }
1094 }
1095
1096 public void disconnect() {
1097 mConnected = false;
1098 mConfig = null;
1099 }
Cody Kestinga75e26b2020-01-05 14:06:39 -08001100
1101 @Override
1102 public synchronized VpnInfo getVpnInfo() {
1103 if (mVpnInfo != null) return mVpnInfo;
1104
1105 return super.getVpnInfo();
1106 }
1107
1108 private void setVpnInfo(VpnInfo vpnInfo) {
1109 mVpnInfo = vpnInfo;
1110 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001111 }
1112
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001113 private void mockVpn(int uid) {
1114 synchronized (mService.mVpns) {
1115 int userId = UserHandle.getUserId(uid);
1116 mMockVpn = new MockVpn(userId);
1117 // This has no effect unless the VPN is actually connected, because things like
1118 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1119 // netId, and check if that network is actually connected.
1120 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001121 }
1122 }
1123
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001124 private void setUidRulesChanged(int uidRules) throws RemoteException {
1125 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1126 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001127
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001128 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
1129 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1130 }
1131
1132 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1133 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1134 }
1135
1136 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1137 volatile boolean mConfigRestrictsAvoidBadWifi;
1138 volatile int mConfigMeteredMultipathPreference;
1139
1140 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001141 super(c, h, r);
1142 }
1143
1144 @Override
1145 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001146 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +09001147 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001148
1149 @Override
1150 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001151 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +08001152 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001153 }
1154
Paul Jensen3d911462015-06-12 06:40:24 -04001155 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001156 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1157 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001158 */
1159 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001160 if (conditionVariable.block(TIMEOUT_MS)) {
1161 return;
1162 }
1163 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001164 }
1165
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001166 private static final int VPN_USER = 0;
1167 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1168 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1169 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1170
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001171 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001172 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001173 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001174
Hugo Benichi64901e52017-10-19 14:42:40 +09001175 MockitoAnnotations.initMocks(this);
1176 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1177
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001178 when(mUserManager.getUsers(eq(true))).thenReturn(
1179 Arrays.asList(new UserInfo[] {
1180 new UserInfo(VPN_USER, "", 0),
1181 }));
Qingxi Li9c5d8b92020-01-08 12:51:49 -08001182 final ApplicationInfo applicationInfo = new ApplicationInfo();
1183 applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
1184 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
1185 .thenReturn(applicationInfo);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001186
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001187 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1188 // http://b/25897652 .
1189 if (Looper.myLooper() == null) {
1190 Looper.prepare();
1191 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001192 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001193
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001194 FakeSettingsProvider.clearSettingsProvider();
1195 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1196 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001197 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1198 LocalServices.addService(
1199 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001200
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001201 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1202 mAlarmManagerThread.start();
1203 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1204
1205 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1206 final ConnectivityService.Dependencies deps = makeDependencies();
1207 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001208 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001209 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001210 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001211 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001212 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001213 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001214 deps);
1215 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1216 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001217
Mike Yuf9729752018-08-17 15:22:05 +08001218 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1219 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1220 verify(mNpm).registerListener(policyListenerCaptor.capture());
1221 mPolicyListener = policyListenerCaptor.getValue();
1222
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001223 // Create local CM before sending system ready so that we can answer
1224 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001225 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001226 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001227 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001228 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001229
1230 // Ensure that the default setting for Captive Portals is used for most tests
1231 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001232 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001233 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001234 }
1235
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001236 private ConnectivityService.Dependencies makeDependencies() {
1237 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1238 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1239 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1240
1241 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1242 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1243 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
1244 doReturn(mNetworkStack).when(deps).getNetworkStack();
1245 doReturn(systemProperties).when(deps).getSystemProperties();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001246 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1247 doReturn(mMetricsService).when(deps).getMetricsLogger();
1248 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1249 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
Chalard Jean587758b2019-11-29 16:41:50 +09001250 doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001251 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1252 doAnswer(inv -> {
1253 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1254 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1255 return mPolicyTracker;
1256 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1257
1258 return deps;
1259 }
1260
1261 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1262 doAnswer(inv -> {
1263 final long when = inv.getArgument(1);
1264 final WakeupMessage wakeupMsg = inv.getArgument(3);
1265 final Handler handler = inv.getArgument(4);
1266
1267 long delayMs = when - SystemClock.elapsedRealtime();
1268 if (delayMs < 0) delayMs = 0;
1269 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1270 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1271 + "ms into the future: " + delayMs);
1272 }
1273 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1274 delayMs);
1275
1276 return null;
1277 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1278 any(WakeupMessage.class), any());
1279
1280 doAnswer(inv -> {
1281 final WakeupMessage wakeupMsg = inv.getArgument(0);
1282 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1283 return null;
1284 }).when(am).cancel(any(WakeupMessage.class));
1285 }
1286
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001287 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001288 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001289 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001290 if (mCellNetworkAgent != null) {
1291 mCellNetworkAgent.disconnect();
1292 mCellNetworkAgent = null;
1293 }
1294 if (mWiFiNetworkAgent != null) {
1295 mWiFiNetworkAgent.disconnect();
1296 mWiFiNetworkAgent = null;
1297 }
1298 if (mEthernetNetworkAgent != null) {
1299 mEthernetNetworkAgent.disconnect();
1300 mEthernetNetworkAgent = null;
1301 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001302 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001303
1304 mCsHandlerThread.quitSafely();
1305 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001306 }
1307
Rubin Xu9e64dc02019-04-23 18:04:14 +01001308 private void mockDefaultPackages() throws Exception {
1309 final String testPackageName = mContext.getPackageName();
1310 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1311 testPackageName, PackageManager.GET_PERMISSIONS);
1312 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1313 new String[] {testPackageName});
1314 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1315 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1316
1317 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1318 Arrays.asList(new PackageInfo[] {
1319 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1320 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1321 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1322 }));
1323 }
1324
Paul Jensend7b6ca92015-05-13 14:05:12 -04001325 private void verifyActiveNetwork(int transport) {
1326 // Test getActiveNetworkInfo()
1327 assertNotNull(mCm.getActiveNetworkInfo());
1328 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1329 // Test getActiveNetwork()
1330 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001331 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001332 if (!NetworkCapabilities.isValidTransport(transport)) {
1333 throw new IllegalStateException("Unknown transport " + transport);
1334 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001335 switch (transport) {
1336 case TRANSPORT_WIFI:
1337 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1338 break;
1339 case TRANSPORT_CELLULAR:
1340 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1341 break;
1342 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001343 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001344 }
1345 // Test getNetworkInfo(Network)
1346 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001347 assertEquals(transportToLegacyType(transport),
1348 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001349 // Test getNetworkCapabilities(Network)
1350 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1351 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1352 }
1353
1354 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001355 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001356 // Test getActiveNetworkInfo()
1357 assertNull(mCm.getActiveNetworkInfo());
1358 // Test getActiveNetwork()
1359 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001360 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001361 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001362 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001363 }
1364
1365 /**
1366 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1367 * broadcasts are received.
1368 */
Chalard Jean407deb72019-11-19 16:14:30 +09001369 private ConditionVariable registerConnectivityBroadcast(final int count) {
1370 return registerConnectivityBroadcastThat(count, intent -> true);
Chalard Jean9ca13772019-11-15 12:08:36 +09001371 }
1372
Chalard Jean407deb72019-11-19 16:14:30 +09001373 private ConditionVariable registerConnectivityBroadcastThat(final int count,
Chalard Jean9ca13772019-11-15 12:08:36 +09001374 @NonNull final Predicate<Intent> filter) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001375 final ConditionVariable cv = new ConditionVariable();
Chalard Jean9ca13772019-11-15 12:08:36 +09001376 final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
1377 intentFilter.addAction(CONNECTIVITY_ACTION_SUPL);
1378 final BroadcastReceiver receiver = new BroadcastReceiver() {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001379 private int remaining = count;
1380 public void onReceive(Context context, Intent intent) {
Chalard Jean9ca13772019-11-15 12:08:36 +09001381 if (!filter.test(intent)) return;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001382 if (--remaining == 0) {
1383 cv.open();
1384 mServiceContext.unregisterReceiver(this);
1385 }
1386 }
Chalard Jean9ca13772019-11-15 12:08:36 +09001387 };
1388 mServiceContext.registerReceiver(receiver, intentFilter);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001389 return cv;
1390 }
1391
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001392 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001393 public void testNetworkTypes() {
1394 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1395 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1396 // will fail. Failing here is much easier to debug.
1397 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1398 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001399 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1400 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1401
1402 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1403 // mocks, this assert exercises the ConnectivityService code path that ensures that
1404 // TYPE_ETHERNET is supported if the ethernet service is running.
1405 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001406 }
1407
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001408 @Test
Chalard Jean9ca13772019-11-15 12:08:36 +09001409 public void testNetworkFeature() throws Exception {
1410 // Connect the cell agent and wait for the connected broadcast.
1411 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1412 mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
Chalard Jean407deb72019-11-19 16:14:30 +09001413 final ConditionVariable cv1 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001414 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE);
1415 mCellNetworkAgent.connect(true);
1416 waitFor(cv1);
1417
1418 // Build legacy request for SUPL.
1419 final NetworkCapabilities legacyCaps = new NetworkCapabilities();
1420 legacyCaps.addTransportType(TRANSPORT_CELLULAR);
1421 legacyCaps.addCapability(NET_CAPABILITY_SUPL);
1422 final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
1423 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
1424
1425 // Send request and check that the legacy broadcast for SUPL is sent correctly.
1426 final TestNetworkCallback callback = new TestNetworkCallback();
Chalard Jean407deb72019-11-19 16:14:30 +09001427 final ConditionVariable cv2 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001428 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1429 mCm.requestNetwork(legacyRequest, callback);
1430 callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1431 waitFor(cv2);
1432
1433 // File another request, withdraw it and make sure no broadcast is sent
Chalard Jean407deb72019-11-19 16:14:30 +09001434 final ConditionVariable cv3 = registerConnectivityBroadcast(1);
Chalard Jean9ca13772019-11-15 12:08:36 +09001435 final TestNetworkCallback callback2 = new TestNetworkCallback();
1436 mCm.requestNetwork(legacyRequest, callback2);
1437 callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1438 mCm.unregisterNetworkCallback(callback2);
1439 assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent
1440 // As the broadcast did not fire, the receiver was not unregistered. Do this now.
1441 mServiceContext.clearRegisteredReceivers();
1442
1443 // Withdraw the request and check that the broadcast for disconnection is sent.
Chalard Jean407deb72019-11-19 16:14:30 +09001444 final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent ->
Chalard Jean9ca13772019-11-15 12:08:36 +09001445 !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected()
1446 && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1447 mCm.unregisterNetworkCallback(callback);
1448 waitFor(cv4);
1449
1450 // Re-file the request and expect the connected broadcast again
Chalard Jean407deb72019-11-19 16:14:30 +09001451 final ConditionVariable cv5 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001452 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1453 final TestNetworkCallback callback3 = new TestNetworkCallback();
1454 mCm.requestNetwork(legacyRequest, callback3);
1455 callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1456 waitFor(cv5);
1457
1458 // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one
1459 // for mobile. Use a small hack to check that both have been sent, but the order is
1460 // not contractual.
1461 final AtomicBoolean vanillaAction = new AtomicBoolean(false);
1462 final AtomicBoolean suplAction = new AtomicBoolean(false);
Chalard Jean407deb72019-11-19 16:14:30 +09001463 final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> {
Chalard Jean9ca13772019-11-15 12:08:36 +09001464 if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
1465 vanillaAction.set(true);
1466 } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) {
1467 suplAction.set(true);
1468 }
1469 return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
1470 });
1471 mCellNetworkAgent.disconnect();
1472 waitFor(cv6);
1473 assertTrue(vanillaAction.get());
1474 assertTrue(suplAction.get());
1475 }
1476
1477 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001478 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001479 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001480 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1481 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001482 assertNull(mCm.getActiveNetworkInfo());
1483 assertNull(mCm.getActiveNetwork());
1484 // Test bringing up validated cellular.
Chalard Jean407deb72019-11-19 16:14:30 +09001485 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001486 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001487 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001488 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001489 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001490 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1491 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1492 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1493 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1494 // Test bringing up validated WiFi.
Chalard Jean407deb72019-11-19 16:14:30 +09001495 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001496 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001497 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001498 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001499 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001500 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1501 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1502 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1503 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1504 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001505 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001506 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001507 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001508 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001509 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001510 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1511 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001512 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001513 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001514 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001515 verifyNoNetwork();
1516 }
1517
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001518 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001519 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1520 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001521 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001522 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001523 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001524 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001525 verifyActiveNetwork(TRANSPORT_WIFI);
1526 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001527 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001528 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001529 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001530 verifyActiveNetwork(TRANSPORT_WIFI);
1531 // Test cellular disconnect.
1532 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001533 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001534 verifyActiveNetwork(TRANSPORT_WIFI);
1535 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001536 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001537 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001538 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001539 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001540 verifyActiveNetwork(TRANSPORT_CELLULAR);
1541 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001542 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001543 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001544 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001545 verifyActiveNetwork(TRANSPORT_WIFI);
1546 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001547 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001548 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001549 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001550 verifyNoNetwork();
1551 }
1552
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001553 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001554 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1555 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001556 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001557 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001558 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001559 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001560 verifyActiveNetwork(TRANSPORT_CELLULAR);
1561 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001562 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001563 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001564 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001565 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001566 verifyActiveNetwork(TRANSPORT_WIFI);
1567 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001568 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001569 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001570 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001571 verifyActiveNetwork(TRANSPORT_CELLULAR);
1572 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001573 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001574 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001575 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001576 verifyNoNetwork();
1577 }
1578
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001579 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001580 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001581 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001582 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001583 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001584 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001585 waitFor(cv);
1586 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001587 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001588 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001589 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001590 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001591 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001592 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001593 waitFor(cv);
1594 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001595 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1596 NET_CAPABILITY_VALIDATED));
1597 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001598 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001599 mCellNetworkAgent.disconnect();
1600 waitFor(cv);
1601 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001602 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001603 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001604 NET_CAPABILITY_VALIDATED));
1605 }
1606
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001607 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001608 public void testCellularOutscoresWeakWifi() throws Exception {
1609 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001610 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001611 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001612 mCellNetworkAgent.connect(true);
1613 waitFor(cv);
1614 verifyActiveNetwork(TRANSPORT_CELLULAR);
1615 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001616 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001617 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001618 mWiFiNetworkAgent.connect(true);
1619 waitFor(cv);
1620 verifyActiveNetwork(TRANSPORT_WIFI);
1621 // Test WiFi getting really weak.
Chalard Jean407deb72019-11-19 16:14:30 +09001622 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001623 mWiFiNetworkAgent.adjustScore(-11);
1624 waitFor(cv);
1625 verifyActiveNetwork(TRANSPORT_CELLULAR);
1626 // Test WiFi restoring signal strength.
Chalard Jean407deb72019-11-19 16:14:30 +09001627 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001628 mWiFiNetworkAgent.adjustScore(11);
1629 waitFor(cv);
1630 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001631 }
1632
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001633 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001634 public void testReapingNetwork() throws Exception {
1635 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1636 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001637 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001638 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001639 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001640 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1641 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001642 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001643 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001644 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001645 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001646 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001647 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001648 mWiFiNetworkAgent.connect(true);
1649 waitFor(cv);
1650 verifyActiveNetwork(TRANSPORT_WIFI);
1651 // Test bringing up unvalidated cellular.
1652 // Expect it to be torn down because it could never be the highest scoring network
1653 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001654 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001655 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001656 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001657 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001658 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001659 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001660 }
1661
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001662 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001663 public void testCellularFallback() throws Exception {
1664 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001665 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001666 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001667 mCellNetworkAgent.connect(true);
1668 waitFor(cv);
1669 verifyActiveNetwork(TRANSPORT_CELLULAR);
1670 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001671 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001672 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001673 mWiFiNetworkAgent.connect(true);
1674 waitFor(cv);
1675 verifyActiveNetwork(TRANSPORT_WIFI);
1676 // Reevaluate WiFi (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001677 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001678 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1679 NET_CAPABILITY_VALIDATED));
1680 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1681 // Should quickly fall back to Cellular.
1682 waitFor(cv);
1683 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1684 NET_CAPABILITY_VALIDATED));
1685 verifyActiveNetwork(TRANSPORT_CELLULAR);
1686 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001687 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001688 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1689 NET_CAPABILITY_VALIDATED));
1690 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1691 // Should quickly fall back to WiFi.
1692 waitFor(cv);
1693 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1694 NET_CAPABILITY_VALIDATED));
1695 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1696 NET_CAPABILITY_VALIDATED));
1697 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001698 }
1699
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001700 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001701 public void testWiFiFallback() throws Exception {
1702 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001703 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001704 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001705 mWiFiNetworkAgent.connect(false);
1706 waitFor(cv);
1707 verifyActiveNetwork(TRANSPORT_WIFI);
1708 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001709 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001710 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001711 mCellNetworkAgent.connect(true);
1712 waitFor(cv);
1713 verifyActiveNetwork(TRANSPORT_CELLULAR);
1714 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001715 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001716 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1717 NET_CAPABILITY_VALIDATED));
1718 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1719 // Should quickly fall back to WiFi.
1720 waitFor(cv);
1721 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1722 NET_CAPABILITY_VALIDATED));
1723 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001724 }
1725
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001726 @Test
1727 public void testRequiresValidation() {
1728 assertTrue(NetworkMonitorUtils.isValidationRequired(
1729 mCm.getDefaultRequest().networkCapabilities));
1730 }
1731
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001732 /**
1733 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1734 * this class receives, by calling expectCallback() exactly once each time a callback is
1735 * received. assertNoCallback may be called at any time.
1736 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001737 private class TestNetworkCallback extends TestableNetworkCallback {
Chalard Jeanb299b842019-09-27 17:13:14 +09001738 TestNetworkCallback() {
1739 super(TEST_CALLBACK_TIMEOUT_MS);
1740 }
1741
Chalard Jean6f4216f2019-06-05 01:40:32 +09001742 @Override
1743 public void assertNoCallback() {
1744 // TODO: better support this use case in TestableNetworkCallback
1745 waitForIdle();
1746 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001747 }
Paul Jensen3d911462015-06-12 06:40:24 -04001748
Erik Klineacdd6392016-07-07 16:50:58 +09001749 @Override
Chalard Jean059c4262019-09-30 17:51:12 +09001750 public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
Chalard Jean6f4216f2019-06-05 01:40:32 +09001751 final long timeoutMs) {
1752 final T callback = super.expectCallback(type, n, timeoutMs);
Chalard Jean059c4262019-09-30 17:51:12 +09001753 if (callback instanceof CallbackEntry.Losing) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09001754 // TODO : move this to the specific test(s) needing this rather than here.
Chalard Jean059c4262019-09-30 17:51:12 +09001755 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001756 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001757 String msg = String.format(
1758 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001759 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001760 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001761 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001762 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001763 }
1764 }
1765
1766 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1767 // only be declared in a static or top level type".
1768 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1769 for (TestNetworkCallback c : callbacks) {
1770 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001771 }
1772 }
1773
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001774 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001775 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001776 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001777 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1778 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001779 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1780 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001781 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1782 .addTransportType(TRANSPORT_WIFI).build();
1783 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1784 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001785 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001786 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1787 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1788
1789 // Test unvalidated networks
Chalard Jean407deb72019-11-19 16:14:30 +09001790 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001791 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001792 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001793 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1794 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001795 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1796 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001797 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001798
Paul Jensen3d911462015-06-12 06:40:24 -04001799 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1800 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001801 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001802 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001803 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1804
Chalard Jean407deb72019-11-19 16:14:30 +09001805 cv = registerConnectivityBroadcast(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001806 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001807 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001808 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1809 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001810 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1811 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001812 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001813
Chalard Jean407deb72019-11-19 16:14:30 +09001814 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001815 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001816 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1817 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001818 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001819 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001820 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001821
Chalard Jean407deb72019-11-19 16:14:30 +09001822 cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001823 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001824 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1825 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001826 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001827 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001828
1829 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001830 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001831 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001832 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1833 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001834 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001835 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001836
Paul Jensen3d911462015-06-12 06:40:24 -04001837 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1838 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001839 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001840 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001841 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1842
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001843 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001844 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001845 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001846 genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001847 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001848 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001849 cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001850 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001851 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001852
Paul Jensen3d911462015-06-12 06:40:24 -04001853 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001854 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1855 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001856 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001857
Paul Jensen3d911462015-06-12 06:40:24 -04001858 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001859 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1860 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001861 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001862 }
1863
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001864 private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
1865 final TestNetworkCallback callback = new TestNetworkCallback();
1866 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
1867 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1868 .addTransportType(TRANSPORT_WIFI).build();
1869 mCm.registerNetworkCallback(wifiRequest, callback);
1870 mCm.registerDefaultNetworkCallback(defaultCallback);
1871
1872 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1873 mWiFiNetworkAgent.connect(false);
1874 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1875 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1876
1877 final LinkProperties newLp = new LinkProperties();
1878 final Uri capportUrl = Uri.parse("https://capport.example.com/api");
1879 final CaptivePortalData capportData = new CaptivePortalData.Builder()
1880 .setCaptive(true).build();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001881
1882 final Uri expectedCapportUrl = sanitized ? null : capportUrl;
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001883 newLp.setCaptivePortalApiUrl(capportUrl);
1884 mWiFiNetworkAgent.sendLinkProperties(newLp);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001885 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001886 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001887 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09001888 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
1889
1890 final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
1891 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(capportData);
1892 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1893 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
1894 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1895 Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001896
1897 final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
1898 assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
1899 assertEquals(expectedCapportData, lp.getCaptivePortalData());
1900 }
1901
1902 @Test
1903 public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
1904 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1905 PERMISSION_DENIED);
1906 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
1907 PERMISSION_DENIED);
1908 doNetworkCallbacksSanitizationTest(true /* sanitized */);
1909 }
1910
1911 @Test
1912 public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
1913 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1914 PERMISSION_GRANTED);
1915 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
1916 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1917 }
1918
1919 @Test
1920 public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
1921 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1922 PERMISSION_DENIED);
1923 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
1924 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1925 }
1926
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001927 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001928 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001929 // This test would be flaky with the default 120ms timer: that is short enough that
1930 // lingered networks are torn down before assertions can be run. We don't want to mock the
1931 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1932 // in detecting races.
1933 mService.mLingerDelayMs = 300;
1934
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001935 NetworkRequest request = new NetworkRequest.Builder()
1936 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1937 .build();
1938 TestNetworkCallback callback = new TestNetworkCallback();
1939 mCm.registerNetworkCallback(request, callback);
1940
1941 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1942 mCm.registerDefaultNetworkCallback(defaultCallback);
1943
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001944 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1945 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1946 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001947
1948 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1949 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1950 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1951
1952 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001953 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1954 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001955 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001956 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001957
1958 mWiFiNetworkAgent.connect(true);
1959 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1960 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001961 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001962 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001963 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001964 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001965 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001966 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001967 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001968
1969 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001970 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001971 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001972 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001973 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001974 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001975 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001976 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001977
1978 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001979 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
1980 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001981 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001982 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001983
1984 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001985 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001986 if (i % 2 == 0) {
1987 mWiFiNetworkAgent.adjustScore(-15);
1988 oldNetwork = mWiFiNetworkAgent;
1989 newNetwork = mCellNetworkAgent;
1990 } else {
1991 mWiFiNetworkAgent.adjustScore(15);
1992 oldNetwork = mCellNetworkAgent;
1993 newNetwork = mWiFiNetworkAgent;
1994
1995 }
Chalard Jean059c4262019-09-30 17:51:12 +09001996 callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001997 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1998 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001999 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002000 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
2001 }
2002 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2003
2004 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
2005 // if the network is still up.
2006 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09002007 // We expect a notification about the capabilities change, and nothing else.
2008 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
2009 defaultCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09002010 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002011 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002012
2013 // Wifi no longer satisfies our listen, which is for an unmetered network.
2014 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002015 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2016
2017 // Disconnect our test networks.
2018 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002019 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002020 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002021 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002022 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002023 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002024 waitForIdle();
2025 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002026
2027 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002028 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002029
2030 // Check that a network is only lingered or torn down if it would not satisfy a request even
2031 // if it validated.
2032 request = new NetworkRequest.Builder().clearCapabilities().build();
2033 callback = new TestNetworkCallback();
2034
2035 mCm.registerNetworkCallback(request, callback);
2036
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002037 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002038 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09002039 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
2040 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002041 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002042 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002043
2044 // Bring up wifi with a score of 20.
2045 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002046 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002047 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09002048 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2049 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002050 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002051 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002052
2053 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002054 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2055 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002056 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002057 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002058 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002059
Chalard Jeanfb830762020-02-20 07:32:12 +00002060 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002061 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002062 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanfb830762020-02-20 07:32:12 +00002063 mWiFiNetworkAgent.adjustScore(50);
2064 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09002065 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002066 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jeanfb830762020-02-20 07:32:12 +00002067 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002068 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002069 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002070
2071 // Tear down wifi.
2072 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002073 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2074 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002075 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002076 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002077 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002078
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002079 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2080 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002081 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002082 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002083 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002084 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002085 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002086 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002087 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002088 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002089 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002090
2091 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002092 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2093 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002094 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002095 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002096 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2097 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002098 waitForIdle();
2099 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002100
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002101 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002102 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002103 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002104 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2105 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002106 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002107 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002108 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002109 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2110 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002111 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002112 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002113 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002114 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002115
2116 NetworkRequest cellRequest = new NetworkRequest.Builder()
2117 .addTransportType(TRANSPORT_CELLULAR).build();
2118 NetworkCallback noopCallback = new NetworkCallback();
2119 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002120 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2121 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002122 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002123 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002124
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002125 // Similar to the above: lingering can start even after the lingered request is removed.
2126 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002127 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002128 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2129 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002130 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002131 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002132
2133 // Cell is now the default network. Pin it with a cell-specific request.
2134 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2135 mCm.requestNetwork(cellRequest, noopCallback);
2136
2137 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002138 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002139 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002140 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2141 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002142 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002143 // The default request is lingering on cell, but nothing happens to cell, and we send no
2144 // callbacks for it, because it's kept up by cellRequest.
2145 callback.assertNoCallback();
2146 // Now unregister cellRequest and expect cell to start lingering.
2147 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002148 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002149
2150 // Let linger run its course.
2151 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002152 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09002153 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002154
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002155 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2156 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2157 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002158 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002159 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002160 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002161 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002162 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002163 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002164 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2165 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002166 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002167
2168 // Let linger run its course.
Chalard Jean059c4262019-09-30 17:51:12 +09002169 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002170
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002171 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002172 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002173 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2174 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2175 trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002176
2177 mCm.unregisterNetworkCallback(callback);
2178 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002179 mCm.unregisterNetworkCallback(trackDefaultCallback);
2180 }
2181
paulhu86e23eb2019-11-05 18:05:05 +08002182 private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
2183 final String testPackageName = mContext.getPackageName();
2184 when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
2185 .thenReturn(buildPackageInfo(true, uid));
2186 mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
2187 }
2188
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002189 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002190 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002191 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08002192 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Chalard Jean1fa777d2018-02-16 16:07:53 +09002193 NetworkRequest request = new NetworkRequest.Builder()
2194 .clearCapabilities()
2195 .build();
2196 TestNetworkCallback callback = new TestNetworkCallback();
2197 mCm.registerNetworkCallback(request, callback);
2198
2199 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2200 mCm.registerDefaultNetworkCallback(defaultCallback);
2201
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002202 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2203 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002204
2205 mCellNetworkAgent.connect(true);
2206 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2207 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2208
2209 // Wifi comes up and cell lingers.
2210 mWiFiNetworkAgent.connect(true);
2211 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2212 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002213 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002214 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2215
2216 // File a request for cellular, then release it.
2217 NetworkRequest cellRequest = new NetworkRequest.Builder()
2218 .addTransportType(TRANSPORT_CELLULAR).build();
2219 NetworkCallback noopCallback = new NetworkCallback();
2220 mCm.requestNetwork(cellRequest, noopCallback);
2221 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002222 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002223
2224 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002225 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002226 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2227 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2228 lingerTimeoutMs);
2229
2230 // Clean up.
2231 mCm.unregisterNetworkCallback(defaultCallback);
2232 mCm.unregisterNetworkCallback(callback);
2233 }
2234
2235 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002236 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002237 NetworkRequest request = new NetworkRequest.Builder()
2238 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2239 .build();
2240 TestNetworkCallback callback = new TestNetworkCallback();
2241 mCm.registerNetworkCallback(request, callback);
2242
2243 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002244 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002245 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002246 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002247
2248 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002249 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002250 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002251 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002252 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002253
2254 // Cell Remains the default.
2255 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2256
2257 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2258 // it's explicitly selected.
2259 mWiFiNetworkAgent.adjustScore(-40);
2260 mWiFiNetworkAgent.adjustScore(40);
2261 callback.assertNoCallback();
2262
2263 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2264 // wifi even though it's unvalidated.
2265 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002266 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002267 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2268
2269 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2270 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002271 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002272 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002273 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002274 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002275 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002276
2277 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2278 // network to disconnect.
2279 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002280 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002281
2282 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002283 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002284 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002285 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002286 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002287 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002288 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2289 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2290
2291 // BUG: the network will no longer linger, even though it's validated and outscored.
2292 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002293 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002294 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002295 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002296 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2297 callback.assertNoCallback();
2298
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002299 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
2300 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
2301 // wifi immediately.
2302 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002303 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002304 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002305 mWiFiNetworkAgent.explicitlySelected(true, true);
2306 mWiFiNetworkAgent.connect(false);
2307 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002308 callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002309 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2310 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002311 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002312
2313 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
2314 // Check that the network is not scored specially and that the device prefers cell data.
2315 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002316 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002317 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002318 mWiFiNetworkAgent.explicitlySelected(false, true);
2319 mWiFiNetworkAgent.connect(false);
2320 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2321 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2322
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002323 // Clean up.
2324 mWiFiNetworkAgent.disconnect();
2325 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002326
Chalard Jean059c4262019-09-30 17:51:12 +09002327 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2328 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002329 }
2330
Chalard Jean05ab6812018-05-02 21:14:54 +09002331 private int[] makeIntArray(final int size, final int value) {
2332 final int[] array = new int[size];
2333 Arrays.fill(array, value);
2334 return array;
2335 }
2336
Paul Jensen85cf78e2015-06-25 13:25:07 -04002337 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002338 // Verify NOT_RESTRICTED is set appropriately
2339 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2340 .build().networkCapabilities;
2341 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2342 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2343 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002344 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002345 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2346 } else {
2347 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2348 }
2349
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002350 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002351 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002352 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2353 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002354 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002355 mServiceContext, "testFactory", filter);
2356 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002357 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002358 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002359 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002360 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002361 int expectedRequestCount = 1;
2362 NetworkCallback networkCallback = null;
2363 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2364 // add one.
2365 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002366 assertFalse(testFactory.getMyStartRequested());
2367 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2368 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002369 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002370 mCm.requestNetwork(request, networkCallback);
2371 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002372 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002373 }
Paul Jensen3d911462015-06-12 06:40:24 -04002374 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002375 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2376 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002377
Paul Jensen85cf78e2015-06-25 13:25:07 -04002378 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002379 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002380 // Rather than create a validated network which complicates things by registering it's
2381 // own NetworkRequest during startup, just bump up the score to cancel out the
2382 // unvalidated penalty.
2383 testAgent.adjustScore(40);
2384 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002385
2386 // When testAgent connects, ConnectivityService will re-send us all current requests with
2387 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2388 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002389 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002390 testAgent.connect(false);
2391 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002392 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002393 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002394 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002395
Paul Jensen85cf78e2015-06-25 13:25:07 -04002396 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002397 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002398 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002399 ConnectivityManager.NetworkCallback[] networkCallbacks =
2400 new ConnectivityManager.NetworkCallback[10];
2401 for (int i = 0; i< networkCallbacks.length; i++) {
2402 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2403 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002404 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002405 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2406 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002407 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2408 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002409
Paul Jensen85cf78e2015-06-25 13:25:07 -04002410 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002411 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002412 for (int i = 0; i < networkCallbacks.length; i++) {
2413 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2414 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002415 testFactory.waitForNetworkRequests(expectedRequestCount);
2416 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002417
Paul Jensen85cf78e2015-06-25 13:25:07 -04002418 // Drop the higher scored network.
2419 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002420 // With the default network disconnecting, the requests are sent with score 0 to factories.
2421 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002422 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002423 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002424 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002425 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2426 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002427
2428 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002429 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002430 handlerThread.quit();
2431 }
2432
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002433 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002434 public void testNetworkFactoryRequests() throws Exception {
2435 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2436 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2437 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2438 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2439 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2440 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2441 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2442 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2443 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2444 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2445 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2446 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2447 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2448 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2449 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2450 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2451 }
2452
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002453 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002454 public void testNoMutableNetworkRequests() throws Exception {
2455 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002456 NetworkRequest request1 = new NetworkRequest.Builder()
2457 .addCapability(NET_CAPABILITY_VALIDATED)
2458 .build();
2459 NetworkRequest request2 = new NetworkRequest.Builder()
2460 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2461 .build();
2462
2463 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002464 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2465 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2466 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2467 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002468 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002469
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002470 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002471 public void testMMSonWiFi() throws Exception {
2472 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002473 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002474 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002475 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002476 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002477 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002478 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002479 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002480
Paul Jensene0988542015-06-25 15:30:08 -04002481 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002482 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09002483 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002484 mWiFiNetworkAgent.connect(true);
2485 waitFor(cv);
2486 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002487
Paul Jensene0988542015-06-25 15:30:08 -04002488 // Register MMS NetworkRequest
2489 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2490 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2491 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2492 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002493
Paul Jensene0988542015-06-25 15:30:08 -04002494 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002495 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002496 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002497 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002498 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002499 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002500
Paul Jensene0988542015-06-25 15:30:08 -04002501 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002502 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002503 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002504 verifyActiveNetwork(TRANSPORT_WIFI);
2505 }
2506
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002507 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002508 public void testMMSonCell() throws Exception {
2509 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002510 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09002511 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002512 mCellNetworkAgent.connect(false);
2513 waitFor(cv);
2514 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002515
Paul Jensene0988542015-06-25 15:30:08 -04002516 // Register MMS NetworkRequest
2517 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2518 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2519 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2520 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002521
Paul Jensene0988542015-06-25 15:30:08 -04002522 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002523 TestNetworkAgentWrapper
2524 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002525 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2526 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002527 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002528 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002529
Paul Jensene0988542015-06-25 15:30:08 -04002530 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002531 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002532 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002533 verifyActiveNetwork(TRANSPORT_CELLULAR);
2534 }
2535
lucaslinf3b59b32019-03-26 17:49:49 +08002536 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002537 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002538 // Register network callback.
2539 NetworkRequest request = new NetworkRequest.Builder()
2540 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2541 .build();
2542 TestNetworkCallback callback = new TestNetworkCallback();
2543 mCm.registerNetworkCallback(request, callback);
2544
2545 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002546 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002547 mCellNetworkAgent.connect(true);
2548 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2549
2550 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002551 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002552 mWiFiNetworkAgent.connectWithPartialConnectivity();
2553 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2554 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2555
2556 // Mobile data should be the default network.
2557 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2558 callback.assertNoCallback();
2559
lucaslinf3b59b32019-03-26 17:49:49 +08002560 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2561 // probe.
lucaslin783f2212019-10-22 18:27:33 +08002562 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
lucasline252a742019-03-12 13:08:03 +08002563 // If the user chooses yes to use this partial connectivity wifi, switch the default
2564 // network to wifi and check if wifi becomes valid or not.
2565 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2566 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002567 // If user accepts partial connectivity network,
2568 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002569 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002570 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002571
lucaslinf3b59b32019-03-26 17:49:49 +08002572 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2573 // validated.
2574 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002575 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002576 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2577 mWiFiNetworkAgent);
2578 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2579 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2580
2581 // Disconnect and reconnect wifi with partial connectivity again.
2582 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002583 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002584 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002585 mWiFiNetworkAgent.connectWithPartialConnectivity();
2586 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2587 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2588
2589 // Mobile data should be the default network.
2590 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2591
2592 // If the user chooses no, disconnect wifi immediately.
2593 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2594 false /* always */);
Chalard Jean059c4262019-09-30 17:51:12 +09002595 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002596
2597 // If user accepted partial connectivity before, and device reconnects to that network
2598 // again, but now the network has full connectivity. The network shouldn't contain
2599 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002600 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002601 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002602 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2603 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002604 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002605
lucaslinf3b59b32019-03-26 17:49:49 +08002606 // If user accepted partial connectivity network before,
2607 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2608 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002609 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002610 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002611 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002612 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2613 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002614
lucasline252a742019-03-12 13:08:03 +08002615 // Wifi should be the default network.
2616 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2617 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002618 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002619
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002620 // The user accepted partial connectivity and selected "don't ask again". Now the user
2621 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2622 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002623 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002624 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2625 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002626 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002627 // If user accepted partial connectivity network before,
2628 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2629 // ConnectivityService#updateNetworkInfo().
lucaslinf3b59b32019-03-26 17:49:49 +08002630 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002631 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002632 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002633 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002634 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
lucaslin783f2212019-10-22 18:27:33 +08002635 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002636
lucaslinf3b59b32019-03-26 17:49:49 +08002637 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2638 // validated.
2639 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2640 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2641 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002642 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002643
2644 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2645 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002646 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002647 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2648 true /* acceptUnvalidated */);
2649
2650 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2651 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2652 // notifyNetworkConnected.
lucaslin783f2212019-10-22 18:27:33 +08002653 mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002654 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002655 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002656 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002657 callback.expectCapabilitiesWith(
2658 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2659 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002660 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002661 }
2662
2663 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002664 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002665 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2666 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2667 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2668 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2669
2670 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2671 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2672 .addCapability(NET_CAPABILITY_VALIDATED).build();
2673 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2674
2675 // Bring up a network with a captive portal.
2676 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002677 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002678 String redirectUrl = "http://android.com/path";
lucaslin783f2212019-10-22 18:27:33 +08002679 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002680 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002681 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002682
2683 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2684 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2685 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2686 .launchCaptivePortalApp();
2687
2688 // Report that the captive portal is dismissed with partial connectivity, and check that
2689 // callbacks are fired.
2690 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002691 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002692 waitForIdle();
2693 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2694 mWiFiNetworkAgent);
2695
2696 // Report partial connectivity is accepted.
lucaslin783f2212019-10-22 18:27:33 +08002697 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002698 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2699 false /* always */);
2700 waitForIdle();
2701 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002702 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002703 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2704 NetworkCapabilities nc =
2705 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2706 mWiFiNetworkAgent);
2707
2708 mCm.unregisterNetworkCallback(captivePortalCallback);
2709 mCm.unregisterNetworkCallback(validatedCallback);
2710 }
2711
2712 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002713 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002714 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2715 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2716 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2717 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2718
2719 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2720 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2721 .addCapability(NET_CAPABILITY_VALIDATED).build();
2722 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002723
2724 // Bring up a network with a captive portal.
2725 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002726 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002727 String firstRedirectUrl = "http://example.com/firstPath";
lucaslin783f2212019-10-22 18:27:33 +08002728 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002729 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002730 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002731
2732 // Take down network.
2733 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002734 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002735 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002736
2737 // Bring up a network with a captive portal.
2738 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002739 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002740 String secondRedirectUrl = "http://example.com/secondPath";
lucaslin783f2212019-10-22 18:27:33 +08002741 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002742 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002743 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002744
2745 // Make captive portal disappear then revalidate.
2746 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
lucaslin783f2212019-10-22 18:27:33 +08002747 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002748 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002749 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002750
2751 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002752 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002753 // Expect no notification to be shown when captive portal disappears by itself
2754 verify(mNotificationManager, never()).notifyAsUser(
2755 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002756
2757 // Break network connectivity.
2758 // Expect NET_CAPABILITY_VALIDATED onLost callback.
lucaslin783f2212019-10-22 18:27:33 +08002759 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002760 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean059c4262019-09-30 17:51:12 +09002761 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002762 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002763
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002764 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002765 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002766 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2767 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2768 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2769 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2770
2771 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2772 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2773 .addCapability(NET_CAPABILITY_VALIDATED).build();
2774 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2775
2776 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002777 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002778 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002779 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002780 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2781
2782 // Check that calling startCaptivePortalApp does nothing.
2783 final int fastTimeoutMs = 100;
2784 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002785 waitForIdle();
2786 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002787 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2788
2789 // Turn into a captive portal.
lucaslin783f2212019-10-22 18:27:33 +08002790 mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002791 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002792 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002793 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002794
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002795 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002796 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002797 waitForIdle();
2798 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2799
2800 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2801 final Bundle testBundle = new Bundle();
2802 final String testKey = "testkey";
2803 final String testValue = "testvalue";
2804 testBundle.putString(testKey, testValue);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09002805 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2806 PERMISSION_GRANTED);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002807 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2808 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2809 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2810 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002811
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002812 // Report that the captive portal is dismissed, and check that callbacks are fired
lucaslin783f2212019-10-22 18:27:33 +08002813 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002814 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002815 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002816 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002817 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2818 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002819
2820 mCm.unregisterNetworkCallback(validatedCallback);
2821 mCm.unregisterNetworkCallback(captivePortalCallback);
2822 }
2823
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002824 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002825 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002826 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2827 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2828 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2829 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2830
2831 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2832 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2833 .addCapability(NET_CAPABILITY_VALIDATED).build();
2834 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2835
2836 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2837 // Bring up a network with a captive portal.
2838 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002839 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002840 String firstRedirectUrl = "http://example.com/firstPath";
2841
lucaslin783f2212019-10-22 18:27:33 +08002842 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002843 mWiFiNetworkAgent.expectDisconnected();
2844 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002845
2846 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002847 }
2848
Remi NGUYEN VAN91aa5bc2019-12-12 12:57:11 +09002849 @Test
2850 public void testCaptivePortalApi() throws Exception {
2851 mServiceContext.setPermission(
2852 android.Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
2853
2854 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2855 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2856 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2857 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2858
2859 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
2860 final String redirectUrl = "http://example.com/firstPath";
2861
2862 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
2863 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2864
2865 final CaptivePortalData testData = new CaptivePortalData.Builder()
2866 .setUserPortalUrl(Uri.parse(redirectUrl))
2867 .setBytesRemaining(12345L)
2868 .build();
2869
2870 mWiFiNetworkAgent.notifyCaptivePortalDataChanged(testData);
2871
2872 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
2873 lp -> testData.equals(lp.getCaptivePortalData()));
2874
2875 final LinkProperties newLps = new LinkProperties();
2876 newLps.setMtu(1234);
2877 mWiFiNetworkAgent.sendLinkProperties(newLps);
2878 // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
2879 captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent,
2880 lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
2881 }
2882
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002883 private NetworkRequest.Builder newWifiRequestBuilder() {
2884 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2885 }
2886
Etan Cohen836ad572018-12-30 17:59:59 -08002887 /**
2888 * Verify request matching behavior with network specifiers.
2889 *
2890 * Note: this test is somewhat problematic since it involves removing capabilities from
2891 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2892 * as a WTF bug in
2893 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2894 * does work.
2895 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002896 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002897 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002898 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2899 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2900 Parcelable {
2901 @Override
2902 public boolean satisfiedBy(NetworkSpecifier other) {
2903 return true;
2904 }
2905
2906 @Override
2907 public int describeContents() {
2908 return 0;
2909 }
2910
2911 @Override
2912 public void writeToParcel(Parcel dest, int flags) {}
2913
2914 @Override
2915 public NetworkSpecifier redact() {
2916 return null;
2917 }
2918 }
2919
2920 // A network specifier that matches either another LocalNetworkSpecifier with the same
2921 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2922 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2923 private String mString;
2924
2925 LocalStringNetworkSpecifier(String string) {
2926 mString = string;
2927 }
2928
2929 @Override
2930 public boolean satisfiedBy(NetworkSpecifier other) {
2931 if (other instanceof LocalStringNetworkSpecifier) {
2932 return TextUtils.equals(mString,
2933 ((LocalStringNetworkSpecifier) other).mString);
2934 }
2935 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2936 return false;
2937 }
2938
2939 @Override
2940 public int describeContents() {
2941 return 0;
2942 }
2943 @Override
2944 public void writeToParcel(Parcel dest, int flags) {}
2945 }
2946
2947
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002948 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002949 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002950 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002951 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2952 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002953 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2954 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002955 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002956 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002957
2958 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2959 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2960 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002961 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002962 TestNetworkCallback cFoo = new TestNetworkCallback();
2963 TestNetworkCallback cBar = new TestNetworkCallback();
2964 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002965 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002966
2967 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2968 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2969 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002970 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002971 mCm.registerNetworkCallback(rFoo, cFoo);
2972 mCm.registerNetworkCallback(rBar, cBar);
2973
Etan Cohen836ad572018-12-30 17:59:59 -08002974 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2975 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2976
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002977 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002978 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002979 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2980 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2981 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2982 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002983 assertNoCallbacks(cFoo, cBar);
2984
Etan Cohen836ad572018-12-30 17:59:59 -08002985 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002986 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002987 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002988 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2989 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002990 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002991 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2992 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08002993 assertEquals(nsFoo,
2994 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002995 cFoo.assertNoCallback();
2996
Etan Cohen836ad572018-12-30 17:59:59 -08002997 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean059c4262019-09-30 17:51:12 +09002998 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002999 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003000 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003001 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3002 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003003 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003004 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
3005 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08003006 assertEquals(nsBar,
3007 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3008 cBar.assertNoCallback();
3009
3010 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
3011 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
3012 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09003013 c.expectCapabilitiesThat(mWiFiNetworkAgent,
3014 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08003015 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09003016 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
3017 (caps) -> caps.getNetworkSpecifier() == null);
3018 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
3019 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08003020 assertNull(
3021 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
3022 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003023 cBar.assertNoCallback();
3024
3025 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean059c4262019-09-30 17:51:12 +09003026 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3027 cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003028 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean059c4262019-09-30 17:51:12 +09003029 c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003030 }
3031
Etan Cohen836ad572018-12-30 17:59:59 -08003032 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09003033 }
3034
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003035 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08003036 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09003037 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003038 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07003039 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003040 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003041
Chalard Jean751bb3f2019-06-19 23:29:58 +09003042 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08003043 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
3044 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07003045 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08003046 mService.requestNetwork(networkCapabilities, null, 0, null,
Qingxi Li9c5d8b92020-01-08 12:51:49 -08003047 ConnectivityManager.TYPE_WIFI, mContext.getPackageName());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003048 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003049
Etan Cohena7434272017-04-03 12:17:51 -07003050 class NonParcelableSpecifier extends NetworkSpecifier {
3051 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
3052 };
3053 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
3054 @Override public int describeContents() { return 0; }
3055 @Override public void writeToParcel(Parcel p, int flags) {}
3056 }
Etan Cohena7434272017-04-03 12:17:51 -07003057
Chalard Jean751bb3f2019-06-19 23:29:58 +09003058 final NetworkRequest.Builder builder =
3059 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
3060 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07003061 builder.setNetworkSpecifier(new NonParcelableSpecifier());
3062 Parcel parcelW = Parcel.obtain();
3063 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003064 });
Etan Cohena7434272017-04-03 12:17:51 -07003065
Chalard Jean751bb3f2019-06-19 23:29:58 +09003066 final NetworkRequest nr =
3067 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
3068 .setNetworkSpecifier(new ParcelableSpecifier())
3069 .build();
Etan Cohena7434272017-04-03 12:17:51 -07003070 assertNotNull(nr);
3071
Chalard Jean751bb3f2019-06-19 23:29:58 +09003072 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07003073 Parcel parcelW = Parcel.obtain();
3074 nr.writeToParcel(parcelW, 0);
3075 byte[] bytes = parcelW.marshall();
3076 parcelW.recycle();
3077
3078 Parcel parcelR = Parcel.obtain();
3079 parcelR.unmarshall(bytes, 0, bytes.length);
3080 parcelR.setDataPosition(0);
3081 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003082 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08003083 }
3084
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003085 @Test
Roshan Piuse38acab2020-01-16 12:17:17 -08003086 public void testNetworkRequestUidSpoofSecurityException() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003087 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07003088 mWiFiNetworkAgent.connect(false);
Roshan Piuse38acab2020-01-16 12:17:17 -08003089 NetworkRequest networkRequest = newWifiRequestBuilder().build();
Etan Cohen859748f2017-04-03 17:42:34 -07003090 TestNetworkCallback networkCallback = new TestNetworkCallback();
Roshan Piuse38acab2020-01-16 12:17:17 -08003091 doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
Chalard Jean751bb3f2019-06-19 23:29:58 +09003092 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07003093 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003094 });
Etan Cohen859748f2017-04-03 17:42:34 -07003095 }
3096
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003097 @Test
paulhu3d67f532019-03-22 16:35:06 +08003098 public void testInvalidSignalStrength() {
3099 NetworkRequest r = new NetworkRequest.Builder()
3100 .addCapability(NET_CAPABILITY_INTERNET)
3101 .addTransportType(TRANSPORT_WIFI)
3102 .setSignalStrength(-75)
3103 .build();
3104 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3105 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003106 assertThrows(SecurityException.class, () ->
3107 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003108
Chalard Jean751bb3f2019-06-19 23:29:58 +09003109 assertThrows(SecurityException.class, () ->
3110 mCm.registerNetworkCallback(r, PendingIntent.getService(
3111 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003112
3113 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003114 assertThrows(IllegalArgumentException.class, () ->
3115 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003116
Chalard Jean751bb3f2019-06-19 23:29:58 +09003117 assertThrows(IllegalArgumentException.class, () ->
3118 mCm.requestNetwork(r, PendingIntent.getService(
3119 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003120 }
3121
3122 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003123 public void testRegisterDefaultNetworkCallback() throws Exception {
3124 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3125 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3126 defaultNetworkCallback.assertNoCallback();
3127
3128 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3129 // whenever Wi-Fi is up. Without this, the mobile network agent is
3130 // reaped before any other activity can take place.
3131 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3132 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3133 .addTransportType(TRANSPORT_CELLULAR).build();
3134 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3135 cellNetworkCallback.assertNoCallback();
3136
3137 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003138 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003139 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003140 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3141 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003142 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003143
3144 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003145 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09003146 mWiFiNetworkAgent.connect(true);
3147 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003148 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003149 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003150
3151 // Bring down cell. Expect no default network callback, since it wasn't the default.
3152 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003153 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003154 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003155 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003156
3157 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003158 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003159 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003160 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003161 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003162 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003163
3164 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3165 // followed by AVAILABLE cell.
3166 mWiFiNetworkAgent.disconnect();
3167 cellNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09003168 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003169 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003170 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003171 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3172 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003173 waitForIdle();
3174 assertEquals(null, mCm.getActiveNetwork());
3175
3176 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003177 final TestNetworkAgentWrapper
3178 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003179 final ArraySet<UidRange> ranges = new ArraySet<>();
3180 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003181 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3182 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003183 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003184 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003185 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3186 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3187
3188 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003189 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003190 waitForIdle();
3191 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003192 }
3193
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003194 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003195 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003196 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003197 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003198 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3199 .addTransportType(TRANSPORT_CELLULAR).build();
3200 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3201
3202 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003203 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09003204 mCellNetworkAgent.connect(true);
3205
Erik Kline1d3db322017-02-28 16:20:20 +09003206 // We should get onAvailable(), onCapabilitiesChanged(), and
3207 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3208 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003209 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003210 cellNetworkCallback.assertNoCallback();
3211
3212 // Update LinkProperties.
3213 final LinkProperties lp = new LinkProperties();
3214 lp.setInterfaceName("foonet_data0");
3215 mCellNetworkAgent.sendLinkProperties(lp);
3216 // We should get onLinkPropertiesChanged().
Chalard Jean059c4262019-09-30 17:51:12 +09003217 cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Chalard Jean6f4216f2019-06-05 01:40:32 +09003218 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003219 cellNetworkCallback.assertNoCallback();
3220
Erik Kline1d3db322017-02-28 16:20:20 +09003221 // Suspend the network.
3222 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003223 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3224 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003225 cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003226 cellNetworkCallback.assertNoCallback();
Chiachang Wanga5d8fe82020-02-12 17:01:59 +08003227 assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
Erik Kline1d3db322017-02-28 16:20:20 +09003228
Erik Klineacdd6392016-07-07 16:50:58 +09003229 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003230 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003231 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003232 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3233 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003234 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003235 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003236 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3237
3238 mCellNetworkAgent.resume();
3239 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3240 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003241 cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09003242 cellNetworkCallback.assertNoCallback();
Chiachang Wanga5d8fe82020-02-12 17:01:59 +08003243 assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
Chalard Jean804b8fb2018-01-30 22:41:41 +09003244
3245 dfltNetworkCallback = new TestNetworkCallback();
3246 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3247 // This time onNetworkSuspended should not be called.
3248 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3249 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003250
Erik Klineacdd6392016-07-07 16:50:58 +09003251 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3252 mCm.unregisterNetworkCallback(cellNetworkCallback);
3253 }
3254
Calvin On1f64f3f2016-10-11 15:10:46 -07003255 private void setCaptivePortalMode(int mode) {
3256 ContentResolver cr = mServiceContext.getContentResolver();
3257 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3258 }
3259
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003260 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003261 ContentResolver cr = mServiceContext.getContentResolver();
3262 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003263 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003264 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003265 }
3266
Erik Kline79c6d052018-03-21 07:18:33 -07003267 private void setPrivateDnsSettings(String mode, String specifier) {
3268 final ContentResolver cr = mServiceContext.getContentResolver();
3269 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3270 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3271 mService.updatePrivateDnsSettings();
3272 waitForIdle();
3273 }
3274
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003275 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003276 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3277 assertNotNull(nc);
3278 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3279 }
3280
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003281 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003282 public void testBackgroundNetworks() throws Exception {
3283 // Create a background request. We can't do this ourselves because ConnectivityService
3284 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003285 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08003286 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003287 final NetworkRequest request = new NetworkRequest.Builder().build();
3288 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3289 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3290 final TestNetworkCallback callback = new TestNetworkCallback();
3291 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3292 mCm.registerNetworkCallback(request, callback);
3293 mCm.registerNetworkCallback(fgRequest, fgCallback);
3294
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003295 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003296 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003297 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3298 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003299 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3300
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003301 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003302 mWiFiNetworkAgent.connect(true);
3303
3304 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003305 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003306 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003307 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003308 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003309 fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003310 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003311 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3312 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3313
3314 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003315 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003316 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09003317 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003318 // Expect a network capabilities update sans FOREGROUND.
3319 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003320 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3321 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3322
3323 // File a cell request and check that cell comes into the foreground.
3324 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3325 .addTransportType(TRANSPORT_CELLULAR).build();
3326 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3327 mCm.requestNetwork(cellRequest, cellCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003328 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3329 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003330 // Expect a network capabilities update with FOREGROUND, because the most recent
3331 // request causes its state to change.
Chalard Jean28e6b262019-11-19 21:30:44 +09003332 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003333 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003334 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3335 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3336
3337 // Release the request. The network immediately goes into the background, since it was not
3338 // lingering.
3339 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09003340 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003341 // Expect a network capabilities update sans FOREGROUND.
3342 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003343 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3344 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3345
3346 // Disconnect wifi and check that cell is foreground again.
3347 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003348 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3349 fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003350 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003351 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3352
3353 mCm.unregisterNetworkCallback(callback);
3354 mCm.unregisterNetworkCallback(fgCallback);
3355 }
3356
Hugo Benichi849b81b2017-05-25 13:42:31 +09003357 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003358 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003359 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003360 // Benchmarks connecting and switching performance in the presence of a large number of
3361 // NetworkRequests.
3362 // 1. File NUM_REQUESTS requests.
3363 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3364 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3365 // and NUM_REQUESTS onAvailable callbacks to fire.
3366 // See how long it took.
3367 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003368 final int REGISTER_TIME_LIMIT_MS = 200;
3369 final int CONNECT_TIME_LIMIT_MS = 60;
3370 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003371 final int UNREGISTER_TIME_LIMIT_MS = 20;
3372
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003373 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3374 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3375 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3376 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3377
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003378 for (int i = 0; i < NUM_REQUESTS; i++) {
3379 callbacks[i] = new NetworkCallback() {
3380 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3381 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3382 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003383 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003384
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003385 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003386 for (NetworkCallback cb : callbacks) {
3387 mCm.registerNetworkCallback(request, cb);
3388 }
3389 });
3390
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003391 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003392 // Don't request that the network validate, because otherwise connect() will block until
3393 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3394 // and we won't actually measure anything.
3395 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003396
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003397 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003398 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003399 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003400 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3401 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3402 onAvailableDispatchingDuration));
3403 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3404 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3405 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003406
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003407 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003408 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003409 mWiFiNetworkAgent.adjustScore(40);
3410 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003411
3412 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003413 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003414 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003415 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3416 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3417 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3418 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3419 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003420
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003421 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003422 for (NetworkCallback cb : callbacks) {
3423 mCm.unregisterNetworkCallback(cb);
3424 }
3425 });
3426 }
3427
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003428 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003429 public void testMobileDataAlwaysOn() throws Exception {
paulhu86e23eb2019-11-05 18:05:05 +08003430 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003431 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3432 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3433 .addTransportType(TRANSPORT_CELLULAR).build();
3434 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3435
3436 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3437 handlerThread.start();
3438 NetworkCapabilities filter = new NetworkCapabilities()
3439 .addTransportType(TRANSPORT_CELLULAR)
3440 .addCapability(NET_CAPABILITY_INTERNET);
3441 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3442 mServiceContext, "testFactory", filter);
3443 testFactory.setScoreFilter(40);
3444
3445 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003446 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003447 testFactory.register();
3448 testFactory.waitForNetworkRequests(1);
3449 assertTrue(testFactory.getMyStartRequested());
3450
3451 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003452 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003453 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3454 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003455 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003456 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003457 assertFalse(testFactory.getMyStartRequested());
3458
3459 ContentResolver cr = mServiceContext.getContentResolver();
3460
3461 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003462 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003463 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003464 testFactory.waitForNetworkRequests(2);
3465 assertTrue(testFactory.getMyStartRequested());
3466
3467 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003468 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003469 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003470 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003471 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003472 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003473 testFactory.waitForNetworkRequests(2);
3474 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3475
3476 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003477 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003478 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003479 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003480
3481 // Turn off mobile data always on and expect the request to disappear...
3482 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003483 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003484 testFactory.waitForNetworkRequests(1);
3485
3486 // ... and cell data to be torn down.
Chalard Jean059c4262019-09-30 17:51:12 +09003487 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003488 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003489
3490 testFactory.unregister();
3491 mCm.unregisterNetworkCallback(cellNetworkCallback);
3492 handlerThread.quit();
3493 }
3494
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003495 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003496 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003497 final ContentResolver cr = mServiceContext.getContentResolver();
3498 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3499
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003500 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003501 String[] values = new String[] {null, "0", "1"};
3502 for (int i = 0; i < values.length; i++) {
3503 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003504 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003505 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003506 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003507 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003508 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003509 }
3510
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003511 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003512
3513 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003514 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003515 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003516 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003517 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003518
3519 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003520 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003521 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003522 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003523 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003524
3525 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003526 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003527 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003528 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003529 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003530 }
3531
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003532 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003533 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003534 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003535
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003536 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003537 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003538
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003539 // File a request for cell to ensure it doesn't go down.
3540 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3541 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3542 .addTransportType(TRANSPORT_CELLULAR).build();
3543 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3544
3545 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3546 mCm.registerDefaultNetworkCallback(defaultCallback);
3547
3548 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3549 .addTransportType(TRANSPORT_WIFI)
3550 .addCapability(NET_CAPABILITY_VALIDATED)
3551 .build();
3552 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3553 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3554
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003555 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003556 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003557
3558 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003559 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003560 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003561 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3562 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003563 Network cellNetwork = mCellNetworkAgent.getNetwork();
3564
3565 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003566 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003567 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003568 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3569 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003570 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3571
3572 // Fail validation on wifi.
lucaslin783f2212019-10-22 18:27:33 +08003573 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003574 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003575 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003576 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003577
3578 // Because avoid bad wifi is off, we don't switch to cellular.
3579 defaultCallback.assertNoCallback();
3580 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3581 NET_CAPABILITY_VALIDATED));
3582 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3583 NET_CAPABILITY_VALIDATED));
3584 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3585
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003586 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3587 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003588 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3589 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003590 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003591 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3592
3593 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003594 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3595 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003596 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003597 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3598
3599 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3600 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003601 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003602 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3603 NET_CAPABILITY_VALIDATED));
3604 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3605 NET_CAPABILITY_VALIDATED));
3606 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3607
3608 // Disconnect and reconnect wifi to clear the one-time switch above.
3609 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003610 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003611 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003612 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3613 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003614 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3615
3616 // Fail validation on wifi and expect the dialog to appear.
lucaslin783f2212019-10-22 18:27:33 +08003617 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003618 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003619 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003620 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003621
3622 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003623 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003624 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003625
3626 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003627 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003628 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3629 NET_CAPABILITY_VALIDATED));
3630 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3631 NET_CAPABILITY_VALIDATED));
3632 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3633
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003634 // Simulate the user turning the cellular fallback setting off and then on.
3635 // We switch to wifi and then to cell.
3636 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003637 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003638 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003639 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3640 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003641 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003642 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003643 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3644
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003645 // If cell goes down, we switch to wifi.
3646 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003647 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003648 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003649 validatedWifiCallback.assertNoCallback();
3650
3651 mCm.unregisterNetworkCallback(cellNetworkCallback);
3652 mCm.unregisterNetworkCallback(validatedWifiCallback);
3653 mCm.unregisterNetworkCallback(defaultCallback);
3654 }
3655
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003656 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003657 public void testMeteredMultipathPreferenceSetting() throws Exception {
3658 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003659 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3660
3661 for (int config : Arrays.asList(0, 3, 2)) {
3662 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003663 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003664 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003665 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003666 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003667
3668 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3669 String msg = String.format("config=%d, setting=%s", config, setting);
3670 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3671 }
3672 }
3673 }
3674
Erik Kline3841a482015-11-25 12:49:38 +09003675 /**
3676 * Validate that a satisfied network request does not trigger onUnavailable() once the
3677 * time-out period expires.
3678 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003679 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003680 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003681 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3682 NetworkCapabilities.TRANSPORT_WIFI).build();
3683 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003684 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003685
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003686 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003687 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003688 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003689 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003690
3691 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003692 networkCallback.assertNoCallback();
3693 }
3694
3695 /**
3696 * Validate that a satisfied network request followed by a disconnected (lost) network does
3697 * not trigger onUnavailable() once the time-out period expires.
3698 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003699 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003700 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003701 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3702 NetworkCapabilities.TRANSPORT_WIFI).build();
3703 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003704 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003705
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003706 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003707 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003708 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003709 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003710 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003711 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003712
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003713 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003714 networkCallback.assertNoCallback();
3715 }
3716
3717 /**
3718 * Validate that when a time-out is specified for a network request the onUnavailable()
3719 * callback is called when time-out expires. Then validate that if network request is
3720 * (somehow) satisfied - the callback isn't called later.
3721 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003722 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003723 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003724 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3725 NetworkCapabilities.TRANSPORT_WIFI).build();
3726 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003727 final int timeoutMs = 10;
3728 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003729
3730 // pass timeout and validate that UNAVAILABLE is called
Chalard Jean059c4262019-09-30 17:51:12 +09003731 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Erik Kline3841a482015-11-25 12:49:38 +09003732
3733 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003734 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003735 mWiFiNetworkAgent.connect(false);
3736 networkCallback.assertNoCallback();
3737 }
3738
3739 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003740 * Validate that when a network request is unregistered (cancelled), no posterior event can
3741 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003742 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003743 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003744 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003745 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3746 NetworkCapabilities.TRANSPORT_WIFI).build();
3747 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003748 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003749
Hugo Benichidfb559a2016-12-20 14:57:49 +09003750 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003751 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003752 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3753 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003754 networkCallback.assertNoCallback();
3755
3756 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003757 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003758 mWiFiNetworkAgent.connect(false);
3759 networkCallback.assertNoCallback();
3760 }
3761
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003762 @Test
3763 public void testUnfulfillableNetworkRequest() throws Exception {
3764 runUnfulfillableNetworkRequest(false);
3765 }
3766
3767 @Test
3768 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3769 runUnfulfillableNetworkRequest(true);
3770 }
3771
Etan Cohenddb720a2019-01-08 12:09:18 -08003772 /**
3773 * Validate the callback flow for a factory releasing a request as unfulfillable.
3774 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003775 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003776 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3777 NetworkCapabilities.TRANSPORT_WIFI).build();
3778 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3779
3780 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3781 handlerThread.start();
3782 NetworkCapabilities filter = new NetworkCapabilities()
3783 .addTransportType(TRANSPORT_WIFI)
3784 .addCapability(NET_CAPABILITY_INTERNET);
3785 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3786 mServiceContext, "testFactory", filter);
3787 testFactory.setScoreFilter(40);
3788
3789 // Register the factory and expect it to receive the default request.
Etan Cohenae574a82019-01-08 12:09:18 -08003790 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003791 testFactory.register();
3792 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3793
3794 assertEquals(1, requests.size()); // have 1 request at this point
3795 int origRequestId = requests.valueAt(0).requestId;
3796
3797 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003798 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003799 mCm.requestNetwork(nr, networkCallback);
3800 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3801
3802 int newRequestId = 0;
3803 for (int i = 0; i < requests.size(); ++i) {
3804 if (requests.valueAt(i).requestId != origRequestId) {
3805 newRequestId = requests.valueAt(i).requestId;
3806 break;
3807 }
3808 }
3809
Etan Cohen22e0fc12019-05-23 08:16:20 -07003810 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003811 if (preUnregister) {
3812 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003813
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003814 // Simulate the factory releasing the request as unfulfillable: no-op since
3815 // the callback has already been unregistered (but a test that no exceptions are
3816 // thrown).
3817 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3818 } else {
3819 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003820 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3821
Chalard Jean059c4262019-09-30 17:51:12 +09003822 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003823 testFactory.waitForRequests();
3824
3825 // unregister network callback - a no-op (since already freed by the
3826 // on-unavailable), but should not fail or throw exceptions.
3827 mCm.unregisterNetworkCallback(networkCallback);
3828 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003829
Etan Cohenddb720a2019-01-08 12:09:18 -08003830 testFactory.unregister();
3831 handlerThread.quit();
3832 }
3833
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003834 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3835
Chalard Jeane7b24752019-06-20 16:01:19 +09003836 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003837
3838 private class CallbackValue {
3839 public CallbackType callbackType;
3840 public int error;
3841
3842 public CallbackValue(CallbackType type) {
3843 this.callbackType = type;
3844 this.error = PacketKeepalive.SUCCESS;
3845 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3846 }
3847
3848 public CallbackValue(CallbackType type, int error) {
3849 this.callbackType = type;
3850 this.error = error;
3851 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3852 }
3853
3854 @Override
3855 public boolean equals(Object o) {
3856 return o instanceof CallbackValue &&
3857 this.callbackType == ((CallbackValue) o).callbackType &&
3858 this.error == ((CallbackValue) o).error;
3859 }
3860
3861 @Override
3862 public String toString() {
3863 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3864 }
3865 }
3866
junyulai7c469172019-01-16 20:23:34 +08003867 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003868
3869 @Override
3870 public void onStarted() {
3871 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3872 }
3873
3874 @Override
3875 public void onStopped() {
3876 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3877 }
3878
3879 @Override
3880 public void onError(int error) {
3881 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3882 }
3883
Chalard Jeane7b24752019-06-20 16:01:19 +09003884 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3885 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003886 }
3887
Chalard Jeane7b24752019-06-20 16:01:19 +09003888 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003889 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3890 }
3891
Chalard Jeane7b24752019-06-20 16:01:19 +09003892 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003893 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3894 }
3895
Chalard Jeane7b24752019-06-20 16:01:19 +09003896 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003897 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3898 }
3899 }
3900
junyulai48eac1d42018-12-27 17:25:29 +08003901 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3902
3903 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3904
3905 private class CallbackValue {
3906 public CallbackType callbackType;
3907 public int error;
3908
3909 CallbackValue(CallbackType type) {
3910 this.callbackType = type;
3911 this.error = SocketKeepalive.SUCCESS;
3912 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3913 }
3914
3915 CallbackValue(CallbackType type, int error) {
3916 this.callbackType = type;
3917 this.error = error;
3918 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3919 }
3920
3921 @Override
3922 public boolean equals(Object o) {
3923 return o instanceof CallbackValue
3924 && this.callbackType == ((CallbackValue) o).callbackType
3925 && this.error == ((CallbackValue) o).error;
3926 }
3927
3928 @Override
3929 public String toString() {
3930 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3931 error);
3932 }
3933 }
3934
3935 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003936 private final Executor mExecutor;
3937
3938 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3939 mExecutor = executor;
3940 }
junyulai48eac1d42018-12-27 17:25:29 +08003941
3942 @Override
3943 public void onStarted() {
3944 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3945 }
3946
3947 @Override
3948 public void onStopped() {
3949 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3950 }
3951
3952 @Override
3953 public void onError(int error) {
3954 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3955 }
3956
Chalard Jeane7b24752019-06-20 16:01:19 +09003957 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3958 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3959
junyulai48eac1d42018-12-27 17:25:29 +08003960 }
3961
Chalard Jeane7b24752019-06-20 16:01:19 +09003962 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003963 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3964 }
3965
Chalard Jeane7b24752019-06-20 16:01:19 +09003966 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003967 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3968 }
3969
Chalard Jeane7b24752019-06-20 16:01:19 +09003970 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003971 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3972 }
junyulai7c469172019-01-16 20:23:34 +08003973
3974 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003975 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08003976 CallbackValue cv = mCallbacks.peek();
3977 assertNull("Unexpected callback: " + cv, cv);
3978 }
junyulai48eac1d42018-12-27 17:25:29 +08003979 }
3980
Chalard Jeane7b24752019-06-20 16:01:19 +09003981 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003982 // Ensure the network is disconnected before we do anything.
3983 if (mWiFiNetworkAgent != null) {
3984 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3985 }
3986
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003987 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09003988 ConditionVariable cv = registerConnectivityBroadcast(1);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003989 mWiFiNetworkAgent.connect(true);
3990 waitFor(cv);
3991 verifyActiveNetwork(TRANSPORT_WIFI);
3992 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003993 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003994 return mWiFiNetworkAgent.getNetwork();
3995 }
3996
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003997 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07003998 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003999 public void testPacketKeepalives() throws Exception {
4000 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4001 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4002 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4003 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4004 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4005
Nathan Harold63dd8132018-02-14 13:09:45 -08004006 final int validKaInterval = 15;
4007 final int invalidKaInterval = 9;
4008
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004009 LinkProperties lp = new LinkProperties();
4010 lp.setInterfaceName("wlan12");
4011 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4012 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4013 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4014 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4015
4016 Network notMyNet = new Network(61234);
4017 Network myNet = connectKeepaliveNetwork(lp);
4018
4019 TestKeepaliveCallback callback = new TestKeepaliveCallback();
4020 PacketKeepalive ka;
4021
4022 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08004023 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004024 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4025
Nathan Harold63dd8132018-02-14 13:09:45 -08004026 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004027 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
4028
Nathan Harold63dd8132018-02-14 13:09:45 -08004029 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004030 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4031
Nathan Harold63dd8132018-02-14 13:09:45 -08004032 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004033 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4034
Nathan Harold63dd8132018-02-14 13:09:45 -08004035 // NAT-T is only supported for IPv4.
4036 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
4037 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004038
Nathan Harold63dd8132018-02-14 13:09:45 -08004039 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004040 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4041
Nathan Harold63dd8132018-02-14 13:09:45 -08004042 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004043 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
4044
Nathan Harold63dd8132018-02-14 13:09:45 -08004045 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004046 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4047
Nathan Harold63dd8132018-02-14 13:09:45 -08004048 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004049 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
4050
4051 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004052 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08004053 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004054 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004055 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004056 ka.stop();
4057 callback.expectStopped();
4058
4059 // Check that deleting the IP address stops the keepalive.
4060 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08004061 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004062 callback.expectStarted();
4063 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4064 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4065 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4066 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
4067 mWiFiNetworkAgent.sendLinkProperties(lp);
4068
4069 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08004070 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004071 callback.expectStarted();
4072 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004073 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004074 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
4075
4076 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09004077 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09004078 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09004079 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004080 ka.stop();
4081
4082 // Reconnect.
4083 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004084 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004085
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004086 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4087 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08004088 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004089 callback.expectStarted();
4090
4091 // The second one gets slot 2.
4092 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4093 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004094 PacketKeepalive ka2 = mCm.startNattKeepalive(
4095 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004096 callback2.expectStarted();
4097
4098 // Now stop the first one and create a third. This also gets slot 1.
4099 ka.stop();
4100 callback.expectStopped();
4101
4102 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4103 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004104 PacketKeepalive ka3 = mCm.startNattKeepalive(
4105 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004106 callback3.expectStarted();
4107
4108 ka2.stop();
4109 callback2.expectStopped();
4110
4111 ka3.stop();
4112 callback3.expectStopped();
4113 }
Udam Sainib7c24872016-01-04 12:16:14 -08004114
Xiao Maa4637112019-02-07 15:03:57 +09004115 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09004116 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
4117 throws Exception {
junyulai06835112019-01-03 18:50:15 +08004118 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004119 final Executor executorInline = (Runnable r) -> r.run();
4120 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08004121 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004122 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004123 }
junyulai06835112019-01-03 18:50:15 +08004124
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004125 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004126 public void testNattSocketKeepalives() throws Exception {
4127 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4128 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08004129 }
4130
4131 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004132 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08004133 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004134 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004135 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4136 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4137 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4138 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4139 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4140
4141 final int validKaInterval = 15;
4142 final int invalidKaInterval = 9;
4143
4144 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004145 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4146 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004147
junyulai48eac1d42018-12-27 17:25:29 +08004148 LinkProperties lp = new LinkProperties();
4149 lp.setInterfaceName("wlan12");
4150 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4151 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4152 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4153 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4154
4155 Network notMyNet = new Network(61234);
4156 Network myNet = connectKeepaliveNetwork(lp);
4157
junyulai7c469172019-01-16 20:23:34 +08004158 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004159
4160 // Attempt to start keepalives with invalid parameters and check for errors.
4161 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004162 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4163 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4164 ka.start(validKaInterval);
4165 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4166 }
junyulai48eac1d42018-12-27 17:25:29 +08004167
4168 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004169 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4170 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4171 ka.start(invalidKaInterval);
4172 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4173 }
junyulai48eac1d42018-12-27 17:25:29 +08004174
4175 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004176 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4177 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4178 ka.start(validKaInterval);
4179 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4180 }
junyulai48eac1d42018-12-27 17:25:29 +08004181
4182 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004183 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4184 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4185 ka.start(validKaInterval);
4186 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4187 }
junyulai48eac1d42018-12-27 17:25:29 +08004188
4189 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004190 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4191 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4192 ka.start(validKaInterval);
4193 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4194 }
junyulai48eac1d42018-12-27 17:25:29 +08004195
4196 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004197 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4198 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4199 ka.start(validKaInterval);
4200 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4201 }
junyulai48eac1d42018-12-27 17:25:29 +08004202
4203 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004204 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004205 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4206 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4207 ka.start(validKaInterval);
4208 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004209 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004210 ka.stop();
4211 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004212
junyulai0c666972019-03-04 22:45:36 +08004213 // Check that keepalive could be restarted.
4214 ka.start(validKaInterval);
4215 callback.expectStarted();
4216 ka.stop();
4217 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004218
junyulai0c666972019-03-04 22:45:36 +08004219 // Check that keepalive can be restarted without waiting for callback.
4220 ka.start(validKaInterval);
4221 callback.expectStarted();
4222 ka.stop();
4223 ka.start(validKaInterval);
4224 callback.expectStopped();
4225 callback.expectStarted();
4226 ka.stop();
4227 callback.expectStopped();
4228 }
junyulai7c469172019-01-16 20:23:34 +08004229
junyulai48eac1d42018-12-27 17:25:29 +08004230 // Check that deleting the IP address stops the keepalive.
4231 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004232 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4233 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4234 ka.start(validKaInterval);
4235 callback.expectStarted();
4236 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4237 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4238 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4239 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4240 mWiFiNetworkAgent.sendLinkProperties(lp);
4241 }
junyulai48eac1d42018-12-27 17:25:29 +08004242
4243 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004244 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4245 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4246 ka.start(validKaInterval);
4247 callback.expectStarted();
4248 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004249 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004250 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004251
junyulai0c666972019-03-04 22:45:36 +08004252 // ... and that stopping it after that has no adverse effects.
4253 waitForIdle();
4254 final Network myNetAlias = myNet;
4255 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4256 ka.stop();
4257 callback.assertNoCallback();
4258 }
junyulai48eac1d42018-12-27 17:25:29 +08004259
4260 // Reconnect.
4261 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004262 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08004263
4264 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4265 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004266 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004267 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4268 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4269 ka.start(validKaInterval);
4270 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004271
junyulai0c666972019-03-04 22:45:36 +08004272 // The second one gets slot 2.
4273 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004274 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4275 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004276 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4277 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4278 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4279 ka2.start(validKaInterval);
4280 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004281
junyulai0c666972019-03-04 22:45:36 +08004282 ka.stop();
4283 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004284
junyulai0c666972019-03-04 22:45:36 +08004285 ka2.stop();
4286 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004287
junyulai0c666972019-03-04 22:45:36 +08004288 testSocket.close();
4289 testSocket2.close();
4290 }
4291 }
junyulai06835112019-01-03 18:50:15 +08004292
junyulai15178152019-03-27 11:00:37 +08004293 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004294 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4295 // assertFalse(isUdpPortInUse(srcPort));
4296 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004297
junyulai06835112019-01-03 18:50:15 +08004298 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004299 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004300 mWiFiNetworkAgent = null;
4301 }
4302
4303 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004304 public void testTcpSocketKeepalives() throws Exception {
4305 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004306 }
4307
4308 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4309 final int srcPortV4 = 12345;
4310 final int srcPortV6 = 23456;
4311 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4312 final InetAddress myIPv6 = InetAddress.getByName("::1");
4313
4314 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004315
4316 final LinkProperties lp = new LinkProperties();
4317 lp.setInterfaceName("wlan12");
4318 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4319 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4320 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4321 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4322
4323 final Network notMyNet = new Network(61234);
4324 final Network myNet = connectKeepaliveNetwork(lp);
4325
4326 final Socket testSocketV4 = new Socket();
4327 final Socket testSocketV6 = new Socket();
4328
junyulai7c469172019-01-16 20:23:34 +08004329 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004330
4331 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4332 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004333 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4334 notMyNet, testSocketV4, executor, callback)) {
4335 ka.start(validKaInterval);
4336 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4337 }
Xiao Maa4637112019-02-07 15:03:57 +09004338
4339 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004340 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4341 myNet, testSocketV4, executor, callback)) {
4342 ka.start(validKaInterval);
4343 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4344 }
Xiao Maa4637112019-02-07 15:03:57 +09004345
4346 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004347 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4348 myNet, testSocketV6, executor, callback)) {
4349 ka.start(validKaInterval);
4350 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4351 }
Xiao Maa4637112019-02-07 15:03:57 +09004352
4353 // Bind the socket address
4354 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4355 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4356
4357 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004358 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4359 myNet, testSocketV4, executor, callback)) {
4360 ka.start(validKaInterval);
4361 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4362 }
Xiao Maa4637112019-02-07 15:03:57 +09004363
4364 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004365 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4366 myNet, testSocketV6, executor, callback)) {
4367 ka.start(validKaInterval);
4368 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4369 }
Xiao Maa4637112019-02-07 15:03:57 +09004370
4371 testSocketV4.close();
4372 testSocketV6.close();
4373
4374 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004375 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004376 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004377 }
4378
junyulai0c666972019-03-04 22:45:36 +08004379 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004380 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4381 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4382 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4383 final int validKaInterval = 15;
4384
4385 // Prepare the target network.
4386 LinkProperties lp = new LinkProperties();
4387 lp.setInterfaceName("wlan12");
4388 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4389 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4390 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004391 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4392 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004393
4394 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4395
4396 // Prepare the target file descriptor, keep only one instance.
4397 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004398 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4399 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004400 final ParcelFileDescriptor testPfd =
4401 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4402 testSocket.close();
4403 assertTrue(isUdpPortInUse(srcPort));
4404
4405 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4406 // block.
4407 try (SocketKeepalive ka = mCm.createNattKeepalive(
4408 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4409 ka.start(validKaInterval);
4410 callback.expectStarted();
4411 ka.stop();
4412 callback.expectStopped();
4413 }
4414
4415 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4416 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4417 // address.
4418 assertTrue(isUdpPortInUse(srcPort));
4419 final InetSocketAddress sa =
4420 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4421 assertEquals(anyIPv4, sa.getAddress());
4422
4423 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004424 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4425 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004426
4427 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004428 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004429 mWiFiNetworkAgent = null;
4430 }
4431
4432 private static boolean isUdpPortInUse(int port) {
4433 try (DatagramSocket ignored = new DatagramSocket(port)) {
4434 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004435 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004436 return true;
4437 }
4438 }
4439
junyulai48eac1d42018-12-27 17:25:29 +08004440 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004441 public void testGetCaptivePortalServerUrl() throws Exception {
4442 String url = mCm.getCaptivePortalServerUrl();
4443 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4444 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004445
4446 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004447 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004448 synchronized(sLock) {
4449 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004450 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004451 }
4452 return sNetwork != null;
4453 }
4454 }
4455
Chalard Jeane7b24752019-06-20 16:01:19 +09004456 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004457 synchronized(sLock) {
4458 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004459 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004460 }
4461 return sNetwork == null;
4462 }
4463 }
4464 }
4465
4466 private void assertPinnedToWifiWithCellDefault() {
4467 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4468 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4469 }
4470
4471 private void assertPinnedToWifiWithWifiDefault() {
4472 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4473 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4474 }
4475
4476 private void assertNotPinnedToWifi() {
4477 assertNull(mCm.getBoundNetworkForProcess());
4478 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4479 }
4480
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004481 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004482 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004483 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4484 .addTransportType(TRANSPORT_WIFI)
4485 .build();
4486 assertNull(mCm.getBoundNetworkForProcess());
4487
4488 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4489 assertNull(mCm.getBoundNetworkForProcess());
4490
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004491 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004492 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004493 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004494 mWiFiNetworkAgent.connect(false);
4495
4496 // When wi-fi connects, expect to be pinned.
4497 assertTrue(TestNetworkPinner.awaitPin(100));
4498 assertPinnedToWifiWithCellDefault();
4499
4500 // Disconnect and expect the pin to drop.
4501 mWiFiNetworkAgent.disconnect();
4502 assertTrue(TestNetworkPinner.awaitUnpin(100));
4503 assertNotPinnedToWifi();
4504
4505 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004506 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004507 mWiFiNetworkAgent.connect(false);
4508 assertFalse(TestNetworkPinner.awaitPin(100));
4509 assertNotPinnedToWifi();
4510
4511 // Pinning while connected causes the pin to take effect immediately.
4512 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4513 assertTrue(TestNetworkPinner.awaitPin(100));
4514 assertPinnedToWifiWithCellDefault();
4515
4516 // Explicitly unpin and expect to use the default network again.
4517 TestNetworkPinner.unpin();
4518 assertNotPinnedToWifi();
4519
4520 // Disconnect cell and wifi.
Chalard Jean407deb72019-11-19 16:14:30 +09004521 ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004522 mCellNetworkAgent.disconnect();
4523 mWiFiNetworkAgent.disconnect();
4524 waitFor(cv);
4525
4526 // Pinning takes effect even if the pinned network is the default when the pin is set...
4527 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004528 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004529 mWiFiNetworkAgent.connect(false);
4530 assertTrue(TestNetworkPinner.awaitPin(100));
4531 assertPinnedToWifiWithWifiDefault();
4532
4533 // ... and is maintained even when that network is no longer the default.
Chalard Jean407deb72019-11-19 16:14:30 +09004534 cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004535 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004536 mCellNetworkAgent.connect(true);
4537 waitFor(cv);
4538 assertPinnedToWifiWithCellDefault();
4539 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004540
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004541 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004542 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004543 // We can only have 99 callbacks, because MultipathPolicyTracker is
4544 // already one of them.
4545 final int MAX_REQUESTS = 99;
4546 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004547 final int INTENTS = 10;
4548 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4549
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004550 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004551 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004552
Hugo Benichi893a7622017-09-29 09:34:08 +09004553 int j = 0;
4554 while (j++ < CALLBACKS / 2) {
4555 NetworkCallback cb = new NetworkCallback();
4556 mCm.requestNetwork(networkRequest, cb);
4557 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004558 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004559 while (j++ < CALLBACKS) {
4560 NetworkCallback cb = new NetworkCallback();
4561 mCm.registerNetworkCallback(networkRequest, cb);
4562 registered.add(cb);
4563 }
4564 j = 0;
4565 while (j++ < INTENTS / 2) {
4566 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4567 mCm.requestNetwork(networkRequest, pi);
4568 registered.add(pi);
4569 }
4570 while (j++ < INTENTS) {
4571 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4572 mCm.registerNetworkCallback(networkRequest, pi);
4573 registered.add(pi);
4574 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004575
Hugo Benichi893a7622017-09-29 09:34:08 +09004576 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004577 assertThrows(TooManyRequestsException.class, () ->
4578 mCm.requestNetwork(networkRequest, new NetworkCallback())
4579 );
4580 assertThrows(TooManyRequestsException.class, () ->
4581 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4582 );
4583 assertThrows(TooManyRequestsException.class, () ->
4584 mCm.requestNetwork(networkRequest,
4585 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4586 );
4587 assertThrows(TooManyRequestsException.class, () ->
4588 mCm.registerNetworkCallback(networkRequest,
4589 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4590 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004591
Hugo Benichi893a7622017-09-29 09:34:08 +09004592 for (Object o : registered) {
4593 if (o instanceof NetworkCallback) {
4594 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004595 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004596 if (o instanceof PendingIntent) {
4597 mCm.unregisterNetworkCallback((PendingIntent)o);
4598 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004599 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004600 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004601
4602 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4603 for (int i = 0; i < MAX_REQUESTS; i++) {
4604 NetworkCallback networkCallback = new NetworkCallback();
4605 mCm.requestNetwork(networkRequest, networkCallback);
4606 mCm.unregisterNetworkCallback(networkCallback);
4607 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004608 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004609
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004610 for (int i = 0; i < MAX_REQUESTS; i++) {
4611 NetworkCallback networkCallback = new NetworkCallback();
4612 mCm.registerNetworkCallback(networkRequest, networkCallback);
4613 mCm.unregisterNetworkCallback(networkCallback);
4614 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004615 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004616
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004617 for (int i = 0; i < MAX_REQUESTS; i++) {
4618 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004619 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004620 mCm.requestNetwork(networkRequest, pendingIntent);
4621 mCm.unregisterNetworkCallback(pendingIntent);
4622 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004623 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004624
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004625 for (int i = 0; i < MAX_REQUESTS; i++) {
4626 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004627 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004628 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4629 mCm.unregisterNetworkCallback(pendingIntent);
4630 }
4631 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004632
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004633 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004634 public void testNetworkInfoOfTypeNone() throws Exception {
Chalard Jean407deb72019-11-19 16:14:30 +09004635 ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004636
4637 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004638 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004639 assertNull(mCm.getActiveNetworkInfo());
4640
4641 Network[] allNetworks = mCm.getAllNetworks();
4642 assertLength(1, allNetworks);
4643 Network network = allNetworks[0];
4644 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4645 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4646
4647 final NetworkRequest request =
4648 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4649 final TestNetworkCallback callback = new TestNetworkCallback();
4650 mCm.registerNetworkCallback(request, callback);
4651
Hugo Benichic1014502017-07-19 10:10:52 +09004652 // Bring up wifi aware network.
lucaslin783f2212019-10-22 18:27:33 +08004653 wifiAware.connect(false, false, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004654 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004655
4656 assertNull(mCm.getActiveNetworkInfo());
4657 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004658 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004659 // of this test. Fix it and uncomment the assert below.
4660 //assertEmpty(mCm.getAllNetworkInfo());
4661
Hugo Benichic1014502017-07-19 10:10:52 +09004662 // Disconnect wifi aware network.
4663 wifiAware.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09004664 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004665 mCm.unregisterNetworkCallback(callback);
4666
4667 verifyNoNetwork();
4668 if (broadcastCV.block(10)) {
4669 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4670 }
4671 }
4672
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004673 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004674 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4675 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4676 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4677 assertNull(mCm.getNetworkForType(TYPE_NONE));
4678 assertNull(mCm.getLinkProperties(TYPE_NONE));
4679 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4680
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004681 assertThrows(IllegalArgumentException.class,
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004682 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004683
4684 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004685 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4686 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004687 // TODO: let test context have configuration application target sdk version
4688 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004689 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4690 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4691 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004692 }
4693
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004694 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004695 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004696 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4697 .addTransportType(TRANSPORT_WIFI).build();
4698 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4699 mCm.registerNetworkCallback(networkRequest, networkCallback);
4700
4701 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004702 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004703 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4704 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4705 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4706 lp.addLinkAddress(myIpv4Address);
4707 lp.addRoute(myIpv4DefaultRoute);
4708
4709 // Verify direct routes are added when network agent is first registered in
4710 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004711 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004712 networkAgent.connect(true);
Chalard Jean059c4262019-09-30 17:51:12 +09004713 networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
4714 networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
4715 CallbackEntry.LinkPropertiesChanged cbi =
4716 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004717 networkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004718 networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004719 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4720 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004721 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004722 Arrays.asList(myIpv4DefaultRoute));
4723 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4724 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4725
4726 // Verify direct routes are added during subsequent link properties updates.
4727 LinkProperties newLp = new LinkProperties(lp);
4728 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4729 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4730 newLp.addLinkAddress(myIpv6Address1);
4731 newLp.addLinkAddress(myIpv6Address2);
4732 networkAgent.sendLinkProperties(newLp);
Chalard Jean059c4262019-09-30 17:51:12 +09004733 cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004734 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004735 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004736 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4737 Arrays.asList(myIpv4DefaultRoute));
4738 mCm.unregisterNetworkCallback(networkCallback);
4739 }
4740
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004741 @Test
4742 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004743 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4744 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004745
Varun Anandd33cbc62019-02-07 14:13:13 -08004746 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4747 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4748
4749 LinkProperties cellLp = new LinkProperties();
4750 cellLp.setInterfaceName(MOBILE_IFNAME);
4751 LinkProperties wifiLp = new LinkProperties();
4752 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004753
4754 // Simple connection should have updated ifaces
4755 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004756 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004757 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004758 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004759 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4760 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004761 reset(mStatsService);
4762
4763 // Default network switch should update ifaces.
4764 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004765 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004766 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004767 assertEquals(wifiLp, mService.getActiveLinkProperties());
4768 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004769 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4770 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004771 reset(mStatsService);
4772
4773 // Disconnect should update ifaces.
4774 mWiFiNetworkAgent.disconnect();
4775 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004776 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004777 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4778 eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004779 reset(mStatsService);
4780
4781 // Metered change should update ifaces
4782 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4783 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004784 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004785 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4786 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004787 reset(mStatsService);
4788
4789 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4790 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004791 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004792 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4793 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004794 reset(mStatsService);
4795
4796 // Captive portal change shouldn't update ifaces
4797 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4798 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004799 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004800 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4801 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004802 reset(mStatsService);
4803
4804 // Roaming change should update ifaces
4805 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4806 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004807 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004808 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4809 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004810 reset(mStatsService);
4811 }
4812
Erik Klinee89953b2018-01-11 16:11:10 +09004813 @Test
4814 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004815 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004816
4817 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004818 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004819
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004820 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09004821 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004822 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004823 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004824
4825 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004826 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004827 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4828 // "is-reachable" testing in order to not program netd with unreachable
4829 // nameservers that it might try repeated to validate.
4830 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004831 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4832 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004833 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004834 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4835 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004836 mCellNetworkAgent.sendLinkProperties(cellLp);
4837 mCellNetworkAgent.connect(false);
4838 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004839
4840 verify(mMockDnsResolver, times(1)).createNetworkCache(
4841 eq(mCellNetworkAgent.getNetwork().netId));
4842 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004843 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004844 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004845
4846 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4847 mCellNetworkAgent.sendLinkProperties(cellLp);
4848 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004849 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004850 mResolverParamsParcelCaptor.capture());
4851 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4852 assertEquals(1, resolvrParams.servers.length);
4853 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004854 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004855 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004856 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004857
4858 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4859 mCellNetworkAgent.sendLinkProperties(cellLp);
4860 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004861 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004862 mResolverParamsParcelCaptor.capture());
4863 resolvrParams = mResolverParamsParcelCaptor.getValue();
4864 assertEquals(2, resolvrParams.servers.length);
4865 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004866 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004867 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004868 assertEquals(2, resolvrParams.tlsServers.length);
4869 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004870 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004871 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004872
4873 final String TLS_SPECIFIER = "tls.example.com";
4874 final String TLS_SERVER6 = "2001:db8:53::53";
4875 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4876 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004877 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4878 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4879
Erik Kline117e7f32018-03-04 21:01:01 +09004880 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004881 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004882 mResolverParamsParcelCaptor.capture());
4883 resolvrParams = mResolverParamsParcelCaptor.getValue();
4884 assertEquals(2, resolvrParams.servers.length);
4885 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004886 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004887 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004888 }
4889
Erik Kline79c6d052018-03-21 07:18:33 -07004890 @Test
lucaslin783f2212019-10-22 18:27:33 +08004891 public void testPrivateDnsNotification() throws Exception {
4892 NetworkRequest request = new NetworkRequest.Builder()
4893 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4894 .build();
4895 TestNetworkCallback callback = new TestNetworkCallback();
4896 mCm.registerNetworkCallback(request, callback);
4897 // Bring up wifi.
4898 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4899 mWiFiNetworkAgent.connect(false);
4900 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4901 // Private DNS resolution failed, checking if the notification will be shown or not.
4902 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4903 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4904 waitForIdle();
4905 // If network validation failed, NetworkMonitor will re-evaluate the network.
4906 // ConnectivityService should filter the redundant notification. This part is trying to
4907 // simulate that situation and check if ConnectivityService could filter that case.
4908 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4909 waitForIdle();
4910 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
4911 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4912 // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
4913 // shown.
4914 mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
4915 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4916 waitForIdle();
4917 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
4918 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
4919 // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
4920 // shown again.
4921 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4922 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4923 waitForIdle();
4924 verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
4925 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4926 }
4927
4928 @Test
Erik Kline79c6d052018-03-21 07:18:33 -07004929 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004930 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004931 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004932
4933 // The default on Android is opportunistic mode ("Automatic").
4934 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4935
dalyk1fcb7392018-03-05 12:42:22 -05004936 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4937 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4938 .addTransportType(TRANSPORT_CELLULAR).build();
4939 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4940
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004941 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07004942 waitForIdle();
4943 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004944 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004945 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004946
4947 final LinkProperties cellLp = new LinkProperties();
4948 cellLp.setInterfaceName(MOBILE_IFNAME);
4949 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4950 // "is-reachable" testing in order to not program netd with unreachable
4951 // nameservers that it might try repeated to validate.
4952 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4953 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4954 MOBILE_IFNAME));
4955 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4956 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4957 MOBILE_IFNAME));
4958 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4959 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4960
4961 mCellNetworkAgent.sendLinkProperties(cellLp);
4962 mCellNetworkAgent.connect(false);
4963 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004964 verify(mMockDnsResolver, times(1)).createNetworkCache(
4965 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08004966 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004967 mResolverParamsParcelCaptor.capture());
4968 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4969 assertEquals(2, resolvrParams.tlsServers.length);
4970 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004971 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07004972 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004973 assertEquals(2, resolvrParams.tlsServers.length);
4974 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004975 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004976 reset(mMockDnsResolver);
Chalard Jean059c4262019-09-30 17:51:12 +09004977 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
4978 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004979 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004980 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4981 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4982 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004983 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004984 assertFalse(cbi.getLp().isPrivateDnsActive());
4985 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004986
4987 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004988 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004989 mResolverParamsParcelCaptor.capture());
4990 resolvrParams = mResolverParamsParcelCaptor.getValue();
4991 assertEquals(2, resolvrParams.servers.length);
4992 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004993 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004994 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004995 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004996
4997 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004998 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004999 mResolverParamsParcelCaptor.capture());
5000 resolvrParams = mResolverParamsParcelCaptor.getValue();
5001 assertEquals(2, resolvrParams.servers.length);
5002 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005003 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08005004 assertEquals(2, resolvrParams.tlsServers.length);
5005 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09005006 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08005007 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05005008 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07005009
dalyk1fcb7392018-03-05 12:42:22 -05005010 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
5011 // Can't test dns configuration for strict mode without properly mocking
5012 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean059c4262019-09-30 17:51:12 +09005013 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005014 mCellNetworkAgent);
5015 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005016 assertTrue(cbi.getLp().isPrivateDnsActive());
5017 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005018 }
5019
5020 @Test
5021 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
5022 // The default on Android is opportunistic mode ("Automatic").
5023 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
5024
5025 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5026 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5027 .addTransportType(TRANSPORT_CELLULAR).build();
5028 mCm.requestNetwork(cellRequest, cellNetworkCallback);
5029
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005030 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05005031 waitForIdle();
5032 LinkProperties lp = new LinkProperties();
5033 mCellNetworkAgent.sendLinkProperties(lp);
5034 mCellNetworkAgent.connect(false);
5035 waitForIdle();
Chalard Jean059c4262019-09-30 17:51:12 +09005036 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
5037 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05005038 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09005039 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
5040 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
5041 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05005042 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005043 assertFalse(cbi.getLp().isPrivateDnsActive());
5044 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005045 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005046 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005047
5048 // Send a validation event for a server that is not part of the current
5049 // resolver config. The validation event should be ignored.
5050 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5051 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
5052 cellNetworkCallback.assertNoCallback();
5053
5054 // Add a dns server to the LinkProperties.
5055 LinkProperties lp2 = new LinkProperties(lp);
5056 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
5057 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean059c4262019-09-30 17:51:12 +09005058 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005059 mCellNetworkAgent);
5060 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005061 assertFalse(cbi.getLp().isPrivateDnsActive());
5062 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005063 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005064 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005065
5066 // Send a validation event containing a hostname that is not part of
5067 // the current resolver config. The validation event should be ignored.
5068 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5069 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
5070 cellNetworkCallback.assertNoCallback();
5071
5072 // Send a validation event where validation failed.
5073 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5074 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
5075 cellNetworkCallback.assertNoCallback();
5076
5077 // Send a validation event where validation succeeded for a server in
5078 // the current resolver config. A LinkProperties callback with updated
5079 // private dns fields should be sent.
5080 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
5081 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean059c4262019-09-30 17:51:12 +09005082 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005083 mCellNetworkAgent);
5084 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005085 assertTrue(cbi.getLp().isPrivateDnsActive());
5086 assertNull(cbi.getLp().getPrivateDnsServerName());
5087 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05005088
5089 // The private dns fields in LinkProperties should be preserved when
5090 // the network agent sends unrelated changes.
5091 LinkProperties lp3 = new LinkProperties(lp2);
5092 lp3.setMtu(1300);
5093 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean059c4262019-09-30 17:51:12 +09005094 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005095 mCellNetworkAgent);
5096 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005097 assertTrue(cbi.getLp().isPrivateDnsActive());
5098 assertNull(cbi.getLp().getPrivateDnsServerName());
5099 checkDnsServers(cbi.getLp(), dnsServers);
5100 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05005101
5102 // Removing the only validated server should affect the private dns
5103 // fields in LinkProperties.
5104 LinkProperties lp4 = new LinkProperties(lp3);
5105 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5106 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean059c4262019-09-30 17:51:12 +09005107 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005108 mCellNetworkAgent);
5109 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005110 assertFalse(cbi.getLp().isPrivateDnsActive());
5111 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005112 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005113 checkDnsServers(cbi.getLp(), dnsServers);
5114 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005115 }
5116
Rubin Xu1bb5c082017-09-05 18:40:49 +01005117 private void checkDirectlyConnectedRoutes(Object callbackObj,
5118 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5119 assertTrue(callbackObj instanceof LinkProperties);
5120 LinkProperties lp = (LinkProperties) callbackObj;
5121
5122 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5123 expectedRoutes.addAll(otherRoutes);
5124 for (LinkAddress address : linkAddresses) {
5125 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5126 // Duplicates in linkAddresses are considered failures
5127 assertTrue(expectedRoutes.add(localRoute));
5128 }
5129 List<RouteInfo> observedRoutes = lp.getRoutes();
5130 assertEquals(expectedRoutes.size(), observedRoutes.size());
5131 assertTrue(observedRoutes.containsAll(expectedRoutes));
5132 }
5133
dalyk1fcb7392018-03-05 12:42:22 -05005134 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5135 assertTrue(callbackObj instanceof LinkProperties);
5136 LinkProperties lp = (LinkProperties) callbackObj;
5137 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5138 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5139 }
5140
Chalard Jean0b214af2018-01-12 17:22:49 +09005141 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005142 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09005143 final int uid = Process.myUid();
5144
5145 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005146 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005147 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5148 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005149 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005150 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5151 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5152 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005153 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5154 .addTransportType(TRANSPORT_WIFI).build();
5155 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005156 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005157 .addTransportType(TRANSPORT_VPN).build();
5158 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005159 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005160 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5161 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005162 mCm.registerDefaultNetworkCallback(defaultCallback);
5163 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005164
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005165 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09005166 mWiFiNetworkAgent.connect(false);
5167
5168 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005169 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005170 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005171 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005172 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005173 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005174
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005175 final TestNetworkAgentWrapper
5176 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean0b214af2018-01-12 17:22:49 +09005177 final ArraySet<UidRange> ranges = new ArraySet<>();
5178 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005179 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5180 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005181 // VPN networks do not satisfy the default request and are automatically validated
5182 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005183 assertFalse(NetworkMonitorUtils.isValidationRequired(
5184 vpnNetworkAgent.getNetworkCapabilities()));
lucaslin783f2212019-10-22 18:27:33 +08005185 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005186
Chalard Jean0b214af2018-01-12 17:22:49 +09005187 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005188 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005189 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005190
5191 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005192 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005193 wifiNetworkCallback.assertNoCallback();
5194 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005195 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5196 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005197
Chalard Jean059c4262019-09-30 17:51:12 +09005198 genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005199 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005200 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
Chalard Jean059c4262019-09-30 17:51:12 +09005201 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005202 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005203
5204 ranges.clear();
5205 vpnNetworkAgent.setUids(ranges);
5206
Chalard Jean059c4262019-09-30 17:51:12 +09005207 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005208 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005209 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005210 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005211
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005212 // TODO : The default network callback should actually get a LOST call here (also see the
5213 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5214 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5215 // can't currently update their UIDs without disconnecting, so this does not matter too
5216 // much, but that is the reason the test here has to check for an update to the
5217 // capabilities instead of the expected LOST then AVAILABLE.
Chalard Jean059c4262019-09-30 17:51:12 +09005218 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005219
Chalard Jean0b214af2018-01-12 17:22:49 +09005220 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005221 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005222 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005223
5224 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005225 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005226 wifiNetworkCallback.assertNoCallback();
5227 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005228 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5229 // happen outside of the test, ConnectivityService does not rematch callbacks.
Chalard Jean059c4262019-09-30 17:51:12 +09005230 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005231
5232 mWiFiNetworkAgent.disconnect();
5233
Chalard Jean059c4262019-09-30 17:51:12 +09005234 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5235 genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5236 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005237 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005238 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005239
5240 vpnNetworkAgent.disconnect();
5241
Chalard Jean059c4262019-09-30 17:51:12 +09005242 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005243 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005244 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005245 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5246 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005247 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005248
5249 mCm.unregisterNetworkCallback(genericNetworkCallback);
5250 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5251 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005252 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005253 }
Chalard Jean26400492018-04-18 20:18:38 +09005254
5255 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005256 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09005257 final int uid = Process.myUid();
5258
5259 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5260 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005261
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005262 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09005263 mWiFiNetworkAgent.connect(true);
5264
5265 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5266 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5267
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005268 TestNetworkAgentWrapper
5269 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09005270 final ArraySet<UidRange> ranges = new ArraySet<>();
5271 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005272 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5273 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005274 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5275 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005276 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005277
5278 defaultCallback.assertNoCallback();
5279 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5280
5281 vpnNetworkAgent.disconnect();
5282 defaultCallback.assertNoCallback();
5283
Varun Anand4fa80e82019-02-06 10:13:38 -08005284 mCm.unregisterNetworkCallback(defaultCallback);
5285 }
5286
5287 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005288 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005289 final int uid = Process.myUid();
5290
5291 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5292 mCm.registerDefaultNetworkCallback(defaultCallback);
5293
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005294 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005295 mWiFiNetworkAgent.connect(true);
5296
5297 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5298 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5299
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005300 TestNetworkAgentWrapper
5301 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005302 final ArraySet<UidRange> ranges = new ArraySet<>();
5303 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005304 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5305 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005306 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
5307 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005308 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005309
Chalard Jean26400492018-04-18 20:18:38 +09005310 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5311 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5312
5313 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005314 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean26400492018-04-18 20:18:38 +09005315 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5316
Chalard Jean26400492018-04-18 20:18:38 +09005317 mCm.unregisterNetworkCallback(defaultCallback);
5318 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005319
5320 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005321 public void testVpnUnvalidated() throws Exception {
5322 final TestNetworkCallback callback = new TestNetworkCallback();
5323 mCm.registerDefaultNetworkCallback(callback);
5324
5325 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005326 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005327 mEthernetNetworkAgent.connect(true);
5328 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5329 callback.assertNoCallback();
5330
5331 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5332 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005333 final TestNetworkAgentWrapper
5334 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005335 final ArraySet<UidRange> ranges = new ArraySet<>();
5336 ranges.add(new UidRange(uid, uid));
5337 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5338 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005339 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
5340 false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005341 mMockVpn.connect();
5342
5343 // Even though the VPN is unvalidated, it becomes the default network for our app.
5344 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5345 // TODO: this looks like a spurious callback.
Chalard Jean059c4262019-09-30 17:51:12 +09005346 callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005347 callback.assertNoCallback();
5348
5349 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5350 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5351 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5352
5353 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5354 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5355 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5356
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005357 assertFalse(NetworkMonitorUtils.isValidationRequired(
5358 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005359 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005360 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005361
5362 // Pretend that the VPN network validates.
lucaslin783f2212019-10-22 18:27:33 +08005363 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005364 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5365 // Expect to see the validated capability, but no other changes, because the VPN is already
5366 // the default network for the app.
5367 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5368 callback.assertNoCallback();
5369
5370 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005371 callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005372 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5373 }
5374
5375 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005376 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005377 final int uid = Process.myUid();
5378
5379 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5380 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5381 .removeCapability(NET_CAPABILITY_NOT_VPN)
5382 .addTransportType(TRANSPORT_VPN)
5383 .build();
5384 NetworkCapabilities nc;
5385 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5386 vpnNetworkCallback.assertNoCallback();
5387
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005388 final TestNetworkAgentWrapper
5389 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005390 final ArraySet<UidRange> ranges = new ArraySet<>();
5391 ranges.add(new UidRange(uid, uid));
5392 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5393 mMockVpn.connect();
5394 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005395 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5396 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005397
5398 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5399 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5400 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5401 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5402 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5403 // For safety reasons a VPN without underlying networks is considered metered.
5404 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5405
5406 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005407 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005408 mCellNetworkAgent.connect(true);
5409
5410 mService.setUnderlyingNetworksForVpn(
5411 new Network[] { mCellNetworkAgent.getNetwork() });
5412
Chalard Jean6f4216f2019-06-05 01:40:32 +09005413 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5414 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005415 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005416 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005417
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005418 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005419 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5420 mWiFiNetworkAgent.connect(true);
5421
5422 mService.setUnderlyingNetworksForVpn(
5423 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5424
Chalard Jean6f4216f2019-06-05 01:40:32 +09005425 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5426 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005427 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005428 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005429
5430 // Don't disconnect, but note the VPN is not using wifi any more.
5431 mService.setUnderlyingNetworksForVpn(
5432 new Network[] { mCellNetworkAgent.getNetwork() });
5433
Chalard Jean6f4216f2019-06-05 01:40:32 +09005434 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5435 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005436 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005437 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005438
5439 // Use Wifi but not cell. Note the VPN is now unmetered.
5440 mService.setUnderlyingNetworksForVpn(
5441 new Network[] { mWiFiNetworkAgent.getNetwork() });
5442
Chalard Jean6f4216f2019-06-05 01:40:32 +09005443 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5444 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005445 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005446 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005447
5448 // Use both again.
5449 mService.setUnderlyingNetworksForVpn(
5450 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5451
Chalard Jean6f4216f2019-06-05 01:40:32 +09005452 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5453 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005454 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005455 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005456
Chalard Jean6b65ec72018-05-18 22:02:56 +09005457 // Disconnect cell. Receive update without even removing the dead network from the
5458 // underlying networks – it's dead anyway. Not metered any more.
5459 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005460 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5461 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005462 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005463 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005464
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005465 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005466 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005467 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5468 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005469 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005470 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005471
5472 mMockVpn.disconnect();
5473 }
junyulai4a192e22018-06-13 15:00:37 +08005474
Mike Yuf9729752018-08-17 15:22:05 +08005475 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005476 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005477 final int uid = Process.myUid();
5478
5479 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5480 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5481 .removeCapability(NET_CAPABILITY_NOT_VPN)
5482 .addTransportType(TRANSPORT_VPN)
5483 .build();
5484 NetworkCapabilities nc;
5485 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5486 vpnNetworkCallback.assertNoCallback();
5487
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005488 final TestNetworkAgentWrapper
5489 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005490 final ArraySet<UidRange> ranges = new ArraySet<>();
5491 ranges.add(new UidRange(uid, uid));
5492 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5493 mMockVpn.connect();
5494 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005495 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5496 false /* isStrictMode */);
Varun Anand4fa80e82019-02-06 10:13:38 -08005497
5498 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5499 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5500 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5501 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5502 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5503 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5504 // In case of no default network, VPN is considered metered.
5505 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5506
5507 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005508 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005509 mCellNetworkAgent.connect(true);
5510
Chalard Jean6f4216f2019-06-05 01:40:32 +09005511 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5512 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005513 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005514 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005515
5516 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005517 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005518 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5519 mWiFiNetworkAgent.connect(true);
5520
Chalard Jean6f4216f2019-06-05 01:40:32 +09005521 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5522 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005523 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005524 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005525
5526 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5527 // the capabilities.
5528 mCellNetworkAgent.disconnect();
5529
5530 // Disconnect wifi too. Now we have no default network.
5531 mWiFiNetworkAgent.disconnect();
5532
Chalard Jean6f4216f2019-06-05 01:40:32 +09005533 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5534 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005535 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005536 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005537
5538 mMockVpn.disconnect();
5539 }
5540
5541 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005542 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005543 // Returns true by default when no network is available.
5544 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005545 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005546 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5547 mWiFiNetworkAgent.connect(true);
5548 waitForIdle();
5549
5550 assertFalse(mCm.isActiveNetworkMetered());
5551 }
5552
5553 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005554 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005555 // Returns true by default when no network is available.
5556 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005557 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005558 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5559 mCellNetworkAgent.connect(true);
5560 waitForIdle();
5561
5562 assertTrue(mCm.isActiveNetworkMetered());
5563 }
5564
5565 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005566 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005567 // Returns true by default when no network is available.
5568 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005569 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005570 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5571 mCellNetworkAgent.connect(true);
5572 waitForIdle();
5573 assertTrue(mCm.isActiveNetworkMetered());
5574
5575 // Connect VPN network. By default it is using current default network (Cell).
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005576 TestNetworkAgentWrapper
5577 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005578 final ArraySet<UidRange> ranges = new ArraySet<>();
5579 final int uid = Process.myUid();
5580 ranges.add(new UidRange(uid, uid));
5581 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5582 mMockVpn.setUids(ranges);
5583 vpnNetworkAgent.connect(true);
5584 mMockVpn.connect();
5585 waitForIdle();
5586 // Ensure VPN is now the active network.
5587 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5588
5589 // Expect VPN to be metered.
5590 assertTrue(mCm.isActiveNetworkMetered());
5591
5592 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005593 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005594 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5595 mWiFiNetworkAgent.connect(true);
5596 waitForIdle();
5597 // VPN should still be the active network.
5598 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5599
5600 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5601 assertFalse(mCm.isActiveNetworkMetered());
5602
5603 // Disconnecting Cell should not affect VPN's meteredness.
5604 mCellNetworkAgent.disconnect();
5605 waitForIdle();
5606
5607 assertFalse(mCm.isActiveNetworkMetered());
5608
5609 // Disconnect WiFi; Now there is no platform default network.
5610 mWiFiNetworkAgent.disconnect();
5611 waitForIdle();
5612
5613 // VPN without any underlying networks is treated as metered.
5614 assertTrue(mCm.isActiveNetworkMetered());
5615
5616 vpnNetworkAgent.disconnect();
5617 mMockVpn.disconnect();
5618 }
5619
5620 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005621 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005622 // Returns true by default when no network is available.
5623 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005624 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005625 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5626 mCellNetworkAgent.connect(true);
5627 waitForIdle();
5628 assertTrue(mCm.isActiveNetworkMetered());
5629
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005630 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005631 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5632 mWiFiNetworkAgent.connect(true);
5633 waitForIdle();
5634 assertFalse(mCm.isActiveNetworkMetered());
5635
5636 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005637 TestNetworkAgentWrapper
5638 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005639 final ArraySet<UidRange> ranges = new ArraySet<>();
5640 final int uid = Process.myUid();
5641 ranges.add(new UidRange(uid, uid));
5642 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5643 mMockVpn.setUids(ranges);
5644 vpnNetworkAgent.connect(true);
5645 mMockVpn.connect();
5646 waitForIdle();
5647 // Ensure VPN is now the active network.
5648 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5649 // VPN is using Cell
5650 mService.setUnderlyingNetworksForVpn(
5651 new Network[] { mCellNetworkAgent.getNetwork() });
5652 waitForIdle();
5653
5654 // Expect VPN to be metered.
5655 assertTrue(mCm.isActiveNetworkMetered());
5656
5657 // VPN is now using WiFi
5658 mService.setUnderlyingNetworksForVpn(
5659 new Network[] { mWiFiNetworkAgent.getNetwork() });
5660 waitForIdle();
5661
5662 // Expect VPN to be unmetered
5663 assertFalse(mCm.isActiveNetworkMetered());
5664
5665 // VPN is using Cell | WiFi.
5666 mService.setUnderlyingNetworksForVpn(
5667 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5668 waitForIdle();
5669
5670 // Expect VPN to be metered.
5671 assertTrue(mCm.isActiveNetworkMetered());
5672
5673 // VPN is using WiFi | Cell.
5674 mService.setUnderlyingNetworksForVpn(
5675 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5676 waitForIdle();
5677
5678 // Order should not matter and VPN should still be metered.
5679 assertTrue(mCm.isActiveNetworkMetered());
5680
5681 // VPN is not using any underlying networks.
5682 mService.setUnderlyingNetworksForVpn(new Network[0]);
5683 waitForIdle();
5684
5685 // VPN without underlying networks is treated as metered.
5686 assertTrue(mCm.isActiveNetworkMetered());
5687
5688 vpnNetworkAgent.disconnect();
5689 mMockVpn.disconnect();
5690 }
5691
5692 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005693 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005694 // Returns true by default when no network is available.
5695 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005696 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005697 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5698 mWiFiNetworkAgent.connect(true);
5699 waitForIdle();
5700 assertFalse(mCm.isActiveNetworkMetered());
5701
5702 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005703 TestNetworkAgentWrapper
5704 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005705 final ArraySet<UidRange> ranges = new ArraySet<>();
5706 final int uid = Process.myUid();
5707 ranges.add(new UidRange(uid, uid));
5708 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5709 mMockVpn.setUids(ranges);
5710 vpnNetworkAgent.connect(true);
5711 mMockVpn.connectAsAlwaysMetered();
5712 waitForIdle();
5713 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5714
5715 // VPN is tracking current platform default (WiFi).
5716 mService.setUnderlyingNetworksForVpn(null);
5717 waitForIdle();
5718
5719 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5720 assertTrue(mCm.isActiveNetworkMetered());
5721
5722 // VPN explicitly declares WiFi as its underlying network.
5723 mService.setUnderlyingNetworksForVpn(
5724 new Network[] { mWiFiNetworkAgent.getNetwork() });
5725 waitForIdle();
5726
5727 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5728 assertTrue(mCm.isActiveNetworkMetered());
5729
5730 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5731 // anyways suppose to be metered.
5732 mWiFiNetworkAgent.disconnect();
5733 waitForIdle();
5734
5735 assertTrue(mCm.isActiveNetworkMetered());
5736
5737 vpnNetworkAgent.disconnect();
5738 }
5739
5740 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005741 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005742 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5743 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5744 .addTransportType(TRANSPORT_CELLULAR)
5745 .build();
5746 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5747
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005748 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005749 mCellNetworkAgent.connect(true);
5750 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5751
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005752 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08005753 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5754
5755 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005756 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005757 cellNetworkCallback.assertNoCallback();
5758
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005759 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005760 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5761
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005762 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005763 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5764
5765 // Restrict the network based on UID rule and NOT_METERED capability change.
5766 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5767 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5768 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5769 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5770 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5771 mCellNetworkAgent);
5772 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005773 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005774 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5775
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005776 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005777 cellNetworkCallback.assertNoCallback();
5778
5779 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005780 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005781 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005782 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005783 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005784 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005785 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5786 cellNetworkCallback.assertNoCallback();
5787
5788 mCm.unregisterNetworkCallback(cellNetworkCallback);
5789 }
5790
5791 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005792 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005793 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5794 mCm.registerDefaultNetworkCallback(defaultCallback);
5795
5796 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005797 setUidRulesChanged(RULE_REJECT_ALL);
5798 setUidRulesChanged(RULE_NONE);
5799 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005800 defaultCallback.assertNoCallback();
5801
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005802 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005803 mCellNetworkAgent.connect(true);
5804 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5805 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5806
5807 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005808 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08005809 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5810 mWiFiNetworkAgent.connect(true);
5811 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5812
5813 // Switch to METERED network. Restrict the use of the network.
5814 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005815 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005816 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5817
5818 // Network becomes NOT_METERED.
5819 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5820 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5821 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5822
5823 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005824 setRestrictBackgroundChanged(true);
5825 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005826 defaultCallback.assertNoCallback();
5827
5828 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005829 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005830 defaultCallback.assertNoCallback();
5831
5832 mCm.unregisterNetworkCallback(defaultCallback);
5833 }
5834
Chalard Jean143124b2019-12-03 22:13:37 +09005835 @Test
5836 public final void testLoseTrusted() throws Exception {
5837 final NetworkRequest trustedRequest = new NetworkRequest.Builder()
5838 .addCapability(NET_CAPABILITY_TRUSTED)
5839 .build();
5840 final TestNetworkCallback trustedCallback = new TestNetworkCallback();
5841 mCm.requestNetwork(trustedRequest, trustedCallback);
5842
5843 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
5844 mCellNetworkAgent.connect(true);
5845 trustedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5846 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005847 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005848
5849 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
5850 mWiFiNetworkAgent.connect(true);
Chalard Jean10c8d542020-02-20 07:32:12 +00005851 trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean143124b2019-12-03 22:13:37 +09005852 verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005853 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005854
5855 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
Chalard Jean143124b2019-12-03 22:13:37 +09005856 trustedCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
5857 verify(mNetworkManagementService).setDefaultNetId(eq(mCellNetworkAgent.getNetwork().netId));
Chalard Jean25be0372019-12-03 22:16:26 +09005858 reset(mNetworkManagementService);
Chalard Jean143124b2019-12-03 22:13:37 +09005859
5860 mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
5861 trustedCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
5862 verify(mNetworkManagementService).clearDefaultNetId();
5863
5864 mCm.unregisterNetworkCallback(trustedCallback);
5865 }
5866
Chalard Jeanb6ec0762019-12-03 16:12:33 +09005867 @Ignore // 40%+ flakiness : figure out why and re-enable.
Chalard Jean587758b2019-11-29 16:41:50 +09005868 @Test
5869 public final void testBatteryStatsNetworkType() throws Exception {
5870 final LinkProperties cellLp = new LinkProperties();
5871 cellLp.setInterfaceName("cell0");
5872 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5873 mCellNetworkAgent.connect(true);
5874 waitForIdle();
5875 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5876 TYPE_MOBILE);
5877 reset(mBatteryStatsService);
5878
5879 final LinkProperties wifiLp = new LinkProperties();
5880 wifiLp.setInterfaceName("wifi0");
5881 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
5882 mWiFiNetworkAgent.connect(true);
5883 waitForIdle();
5884 verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(),
5885 TYPE_WIFI);
5886 reset(mBatteryStatsService);
5887
Chalard Jean587758b2019-11-29 16:41:50 +09005888 mCellNetworkAgent.disconnect();
5889
5890 cellLp.setInterfaceName("wifi0");
5891 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5892 mCellNetworkAgent.connect(true);
5893 waitForIdle();
5894 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5895 TYPE_MOBILE);
5896 }
5897
junyulai4a192e22018-06-13 15:00:37 +08005898 /**
5899 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5900 */
5901 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5902 InterfaceConfiguration cfg = new InterfaceConfiguration();
5903 cfg.setHardwareAddress("11:22:33:44:55:66");
5904 cfg.setLinkAddress(la);
5905 return cfg;
5906 }
5907
5908 /**
5909 * Make expected stack link properties, copied from Nat464Xlat.
5910 */
5911 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5912 LinkAddress clatAddress = la;
5913 LinkProperties stacked = new LinkProperties();
5914 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5915 RouteInfo ipv4Default = new RouteInfo(
5916 new LinkAddress(Inet4Address.ANY, 0),
5917 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5918 stacked.addRoute(ipv4Default);
5919 stacked.addLinkAddress(clatAddress);
5920 return stacked;
5921 }
5922
5923 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005924 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08005925 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5926 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005927 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5928 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005929 final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(),
5930 MOBILE_IFNAME);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00005931 final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
5932 final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005933 final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(),
5934 CLAT_PREFIX + MOBILE_IFNAME);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005935
junyulai4a192e22018-06-13 15:00:37 +08005936 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5937 .addTransportType(TRANSPORT_CELLULAR)
5938 .addCapability(NET_CAPABILITY_INTERNET)
5939 .build();
5940 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5941 mCm.registerNetworkCallback(networkRequest, networkCallback);
5942
Lorenzo Colittid593e292019-02-19 13:21:56 +09005943 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005944 final LinkProperties cellLp = new LinkProperties();
5945 cellLp.setInterfaceName(MOBILE_IFNAME);
5946 cellLp.addLinkAddress(myIpv6);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005947 cellLp.addRoute(defaultRoute);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00005948 cellLp.addRoute(ipv6Subnet);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005949 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005950 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005951 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005952 reset(mMockNetd);
Chalard Jean587758b2019-11-29 16:41:50 +09005953 reset(mBatteryStatsService);
junyulai4a192e22018-06-13 15:00:37 +08005954
Lorenzo Colittid593e292019-02-19 13:21:56 +09005955 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005956 mCellNetworkAgent.connect(true);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005957 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
Chalard Jean587758b2019-11-29 16:41:50 +09005958 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005959
5960 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00005961 assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute);
Luke Huanga24d5d82019-04-09 18:41:49 +08005962 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
Chalard Jean587758b2019-11-29 16:41:50 +09005963 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5964 TYPE_MOBILE);
Luke Huanga24d5d82019-04-09 18:41:49 +08005965
junyulai4a192e22018-06-13 15:00:37 +08005966 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005967 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005968
Lorenzo Colittid593e292019-02-19 13:21:56 +09005969 // Switching default network updates TCP buffer sizes.
5970 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5971
5972 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5973 // the NAT64 prefix was removed because one was never discovered.
5974 cellLp.addLinkAddress(myIpv4);
5975 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005976 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00005977 assertRoutesAdded(cellNetId, ipv4Subnet);
Luke Huang65914772019-03-16 00:31:46 +08005978 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005979 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005980
Chalard Jean587758b2019-11-29 16:41:50 +09005981 // Make sure BatteryStats was not told about any v4- interfaces, as none should have
5982 // come online yet.
5983 waitForIdle();
5984 verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt());
5985
Lorenzo Colittid593e292019-02-19 13:21:56 +09005986 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005987 verifyNoMoreInteractions(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005988 reset(mNetworkManagementService);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005989 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005990 reset(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00005991 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5992 .thenReturn(getClatInterfaceConfig(myIpv4));
Lorenzo Colittid593e292019-02-19 13:21:56 +09005993
5994 // Remove IPv4 address. Expect prefix discovery to be started again.
5995 cellLp.removeLinkAddress(myIpv4);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005996 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005997 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005998 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00005999 assertRoutesRemoved(cellNetId, ipv4Subnet);
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 Worker7d66c262020-03-04 04:53:17 +00006018 assertRoutesAdded(cellNetId, 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 Worker7d66c262020-03-04 04:53:17 +00006044 cellLp.addRoute(ipv4Subnet);
junyulai4a192e22018-06-13 15:00:37 +08006045 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006046 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006047 assertRoutesAdded(cellNetId, ipv4Subnet);
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());
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006058 assertRoutesRemoved(cellNetId, stackedDefault);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006059
6060 // The interface removed callback happens but has no effect after stop is called.
6061 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
6062 networkCallback.assertNoCallback();
6063
Lorenzo Colittid593e292019-02-19 13:21:56 +09006064 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006065 verifyNoMoreInteractions(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006066 reset(mNetworkManagementService);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006067 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08006068 reset(mMockDnsResolver);
Automerger Merge Workerd9375e42020-02-27 01:16:45 +00006069 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
6070 .thenReturn(getClatInterfaceConfig(myIpv4));
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006071
Lorenzo Colittid593e292019-02-19 13:21:56 +09006072 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
6073 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6074 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006075 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6076 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006077
6078 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006079 cellLp.removeLinkAddress(myIpv4);
6080 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
6081 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
6082 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09006083 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006084 assertRoutesRemoved(cellNetId, ipv4Subnet); // Directly-connected routes auto-added.
Luke Huang65914772019-03-16 00:31:46 +08006085 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09006086 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
6087 kNat64PrefixString, 96);
Chalard Jean059c4262019-09-30 17:51:12 +09006088 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006089 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
6090
Lorenzo Colittid593e292019-02-19 13:21:56 +09006091
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006092 // Clat iface comes up. Expect stacked link to be added.
6093 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006094 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6095 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006096 assertRoutesAdded(cellNetId, stackedDefault);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006097
6098 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09006099 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
6100 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006101 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6102 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006103 assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
6104
6105 // Stop has no effect because clat is already stopped.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006106 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09006107 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
6108 (lp) -> lp.getStackedLinks().size() == 0);
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006109 verifyNoMoreInteractions(mMockNetd);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09006110
6111 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08006112 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006113 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09006114 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08006115 mCm.unregisterNetworkCallback(networkCallback);
6116 }
Chiachang Wanga6093042018-09-28 22:42:48 +08006117
6118 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006119 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08006120 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6121 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6122 .addCapability(NET_CAPABILITY_INTERNET)
6123 .build();
6124 mCm.registerNetworkCallback(networkRequest, networkCallback);
6125
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006126 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08006127 final LinkProperties cellLp = new LinkProperties();
6128 cellLp.setInterfaceName(MOBILE_IFNAME);
6129 mCellNetworkAgent.sendLinkProperties(cellLp);
6130 reset(mNetworkManagementService);
6131 mCellNetworkAgent.connect(true);
6132 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6133 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6134 eq(ConnectivityManager.TYPE_MOBILE));
6135
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006136 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006137 final LinkProperties wifiLp = new LinkProperties();
6138 wifiLp.setInterfaceName(WIFI_IFNAME);
6139 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6140
6141 // Network switch
6142 reset(mNetworkManagementService);
6143 mWiFiNetworkAgent.connect(true);
6144 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006145 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006146 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6147 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6148 eq(ConnectivityManager.TYPE_WIFI));
6149 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6150
6151 // Disconnect wifi and switch back to cell
6152 reset(mNetworkManagementService);
6153 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006154 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006155 assertNoCallbacks(networkCallback);
6156 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6157 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6158 eq(ConnectivityManager.TYPE_MOBILE));
6159
6160 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006161 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006162 wifiLp.setInterfaceName(WIFI_IFNAME);
6163 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6164 mWiFiNetworkAgent.connect(true);
6165 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006166 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006167 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6168
6169 // Disconnect cell
6170 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006171 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006172 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006173 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006174 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6175 // sent as network being switched. Ensure rule removal for cell will not be triggered
6176 // unexpectedly before network being removed.
6177 waitForIdle();
6178 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006179 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6180 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08006181 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006182
6183 // Disconnect wifi
Chalard Jean407deb72019-11-19 16:14:30 +09006184 ConditionVariable cv = registerConnectivityBroadcast(1);
Chiachang Wanga6093042018-09-28 22:42:48 +08006185 reset(mNetworkManagementService);
6186 mWiFiNetworkAgent.disconnect();
6187 waitFor(cv);
6188 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6189
6190 // Clean up
6191 mCm.unregisterNetworkCallback(networkCallback);
6192 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006193
Chalard Jeane7b24752019-06-20 16:01:19 +09006194 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006195 String[] values = tcpBufferSizes.split(",");
6196 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6197 String wmemValues = String.join(" ", values[3], values[4], values[5]);
Chalard Jeane7b24752019-06-20 16:01:19 +09006198 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006199 reset(mMockNetd);
6200 }
6201
6202 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006203 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006204 final String testTcpBufferSizes = "1,2,3,4,5,6";
paulhu66269b32019-08-30 19:24:36 +08006205 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6206 .addTransportType(TRANSPORT_CELLULAR)
6207 .addCapability(NET_CAPABILITY_INTERNET)
6208 .build();
6209 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6210 mCm.registerNetworkCallback(networkRequest, networkCallback);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006211
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006212 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006213 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006214 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006215 mCellNetworkAgent.connect(false);
paulhu66269b32019-08-30 19:24:36 +08006216 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006217 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6218
6219 // Change link Properties should have updated tcp buffer size.
6220 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006221 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006222 mCellNetworkAgent.sendLinkProperties(lp);
Chalard Jean059c4262019-09-30 17:51:12 +09006223 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006224 verifyTcpBufferSizeChange(testTcpBufferSizes);
paulhu66269b32019-08-30 19:24:36 +08006225
6226 // Clean up.
6227 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006228 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
paulhu66269b32019-08-30 19:24:36 +08006229 networkCallback.assertNoCallback();
6230 mCm.unregisterNetworkCallback(networkCallback);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006231 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006232
6233 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006234 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006235 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006236 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006237 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6238 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6239 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6240 }
6241
6242 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006243 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006244 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006245 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006246 mWiFiNetworkAgent.connect(true);
6247 waitForIdle();
6248 assertNull(mService.getProxyForNetwork(null));
6249
6250 final LinkProperties testLinkProperties = new LinkProperties();
6251 testLinkProperties.setHttpProxy(testProxyInfo);
6252
6253 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6254 waitForIdle();
6255
6256 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6257 }
6258
6259 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006260 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006261 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6262
6263 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006264 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006265 mWiFiNetworkAgent.connect(true);
6266 waitForIdle();
6267 assertNull(mService.getProxyForNetwork(null));
6268
6269 // Set up a VPN network with a proxy
6270 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006271 final TestNetworkAgentWrapper
6272 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006273 final ArraySet<UidRange> ranges = new ArraySet<>();
6274 ranges.add(new UidRange(uid, uid));
6275 mMockVpn.setUids(ranges);
6276 LinkProperties testLinkProperties = new LinkProperties();
6277 testLinkProperties.setHttpProxy(testProxyInfo);
6278 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6279 waitForIdle();
6280
6281 // Connect to VPN with proxy
6282 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6283 vpnNetworkAgent.connect(true);
6284 mMockVpn.connect();
6285 waitForIdle();
6286
6287 // Test that the VPN network returns a proxy, and the WiFi does not.
6288 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6289 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6290 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6291
6292 // Test that the VPN network returns no proxy when it is set to null.
6293 testLinkProperties.setHttpProxy(null);
6294 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6295 waitForIdle();
6296 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6297 assertNull(mService.getProxyForNetwork(null));
6298
6299 // Set WiFi proxy and check that the vpn proxy is still null.
6300 testLinkProperties.setHttpProxy(testProxyInfo);
6301 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6302 waitForIdle();
6303 assertNull(mService.getProxyForNetwork(null));
6304
6305 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6306 // correct proxy setting.
6307 vpnNetworkAgent.disconnect();
6308 waitForIdle();
6309 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6310 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6311 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6312 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006313
6314 @Test
6315 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6316 LinkProperties lp = new LinkProperties();
6317 lp.setInterfaceName("tun0");
6318 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6319 // The uid range needs to cover the test app so the network is visible to it.
6320 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006321 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006322
6323 // Connected VPN should have interface rules set up. There are two expected invocations,
6324 // one during VPN uid update, one during VPN LinkProperties update
6325 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6326 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6327 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6328 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6329 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6330
6331 vpnNetworkAgent.disconnect();
6332 waitForIdle();
6333
6334 // Disconnected VPN should have interface rules removed
6335 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6336 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6337 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6338 }
6339
6340 @Test
6341 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6342 LinkProperties lp = new LinkProperties();
6343 lp.setInterfaceName("tun0");
6344 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6345 // The uid range needs to cover the test app so the network is visible to it.
6346 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006347 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6348 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006349
6350 // Legacy VPN should not have interface rules set up
6351 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6352 }
6353
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09006354 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006355 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6356 throws Exception {
6357 LinkProperties lp = new LinkProperties();
6358 lp.setInterfaceName("tun0");
6359 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6360 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6361 // The uid range needs to cover the test app so the network is visible to it.
6362 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006363 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6364 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006365
6366 // IPv6 unreachable route should not be misinterpreted as a default route
6367 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6368 }
6369
6370 @Test
6371 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6372 LinkProperties lp = new LinkProperties();
6373 lp.setInterfaceName("tun0");
6374 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6375 // The uid range needs to cover the test app so the network is visible to it.
6376 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006377 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006378
6379 // Connected VPN should have interface rules set up. There are two expected invocations,
6380 // one during VPN uid update, one during VPN LinkProperties update
6381 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6382 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6383 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6384 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6385
6386 reset(mMockNetd);
6387 InOrder inOrder = inOrder(mMockNetd);
6388 lp.setInterfaceName("tun1");
6389 vpnNetworkAgent.sendLinkProperties(lp);
6390 waitForIdle();
6391 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6392 // removed first, then new rules added)
6393 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6394 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6395 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6396 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6397
6398 reset(mMockNetd);
6399 lp = new LinkProperties();
6400 lp.setInterfaceName("tun1");
6401 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6402 vpnNetworkAgent.sendLinkProperties(lp);
6403 waitForIdle();
6404 // VPN not routing everything should no longer have interface filtering rules
6405 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6406 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6407
6408 reset(mMockNetd);
6409 lp = new LinkProperties();
6410 lp.setInterfaceName("tun1");
6411 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6412 vpnNetworkAgent.sendLinkProperties(lp);
6413 waitForIdle();
6414 // Back to routing all IPv6 traffic should have filtering rules
6415 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6416 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6417 }
6418
6419 @Test
6420 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6421 LinkProperties lp = new LinkProperties();
6422 lp.setInterfaceName("tun0");
6423 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6424 // The uid range needs to cover the test app so the network is visible to it.
6425 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006426 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006427 Collections.singleton(vpnRange));
6428
6429 reset(mMockNetd);
6430 InOrder inOrder = inOrder(mMockNetd);
6431
6432 // Update to new range which is old range minus APP1, i.e. only APP2
6433 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6434 new UidRange(vpnRange.start, APP1_UID - 1),
6435 new UidRange(APP1_UID + 1, vpnRange.stop)));
6436 vpnNetworkAgent.setUids(newRanges);
6437 waitForIdle();
6438
6439 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6440 // Verify old rules are removed before new rules are added
6441 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6442 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6443 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6444 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6445 }
6446
Valentin Iftimec86ebba2019-09-24 13:32:13 +02006447 @Test
6448 public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
6449 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6450
6451 LinkProperties wifiLp = new LinkProperties();
6452 wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
6453 wifiLp.setWakeOnLanSupported(false);
6454
6455 // Default network switch should update ifaces.
6456 mWiFiNetworkAgent.connect(false);
6457 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6458 waitForIdle();
6459
6460 // ConnectivityService should have changed the WakeOnLanSupported to true
6461 wifiLp.setWakeOnLanSupported(true);
6462 assertEquals(wifiLp, mService.getActiveLinkProperties());
6463 }
6464
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006465 private void setupLocationPermissions(
6466 int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
6467 final ApplicationInfo applicationInfo = new ApplicationInfo();
6468 applicationInfo.targetSdkVersion = targetSdk;
6469 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
6470 .thenReturn(applicationInfo);
6471
6472 when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
6473
6474 if (op != null) {
6475 when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
6476 .thenReturn(AppOpsManager.MODE_ALLOWED);
6477 }
6478
6479 if (perm != null) {
6480 mServiceContext.setPermission(perm, PERMISSION_GRANTED);
6481 }
6482 }
6483
6484 private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
6485 final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
6486
6487 return mService
6488 .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
6489 .getOwnerUid();
6490 }
6491
Qingxi Li7cf06622020-01-17 17:54:27 -08006492 @Test
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006493 public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
6494 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6495 Manifest.permission.ACCESS_FINE_LOCATION);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006496
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006497 final int myUid = Process.myUid();
6498 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6499 }
Qingxi Li7cf06622020-01-17 17:54:27 -08006500
Qingxi Li9c5d8b92020-01-08 12:51:49 -08006501 @Test
6502 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception {
6503 setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
6504 Manifest.permission.ACCESS_COARSE_LOCATION);
6505
6506 final int myUid = Process.myUid();
6507 assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6508 }
6509
6510 @Test
6511 public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception {
6512 // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
6513 setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
6514 Manifest.permission.ACCESS_FINE_LOCATION);
6515
6516 final int myUid = Process.myUid();
6517 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6518 }
6519
6520 @Test
6521 public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception {
6522 // Test that even with fine location permission, not being the owner leads to sanitization.
6523 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6524 Manifest.permission.ACCESS_FINE_LOCATION);
6525
6526 final int myUid = Process.myUid();
6527 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
6528 }
6529
6530 @Test
6531 public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception {
6532 // Test that not having fine location permission leads to sanitization.
6533 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
6534 Manifest.permission.ACCESS_COARSE_LOCATION);
6535
6536 // Test that without the location permission, the owner field is sanitized.
6537 final int myUid = Process.myUid();
6538 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
6539 }
6540
6541 @Test
6542 public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception {
6543 setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
6544
6545 // Test that without the location permission, the owner field is sanitized.
6546 final int myUid = Process.myUid();
6547 assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
Qingxi Li7cf06622020-01-17 17:54:27 -08006548 }
6549
Benedict Wong5d50ce82020-01-20 22:14:59 -08006550 private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
6551 throws Exception {
6552 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
6553 establishVpn(new LinkProperties(), vpnOwnerUid, vpnRange);
6554 mMockVpn.setVpnType(vpnType);
6555
6556 final VpnInfo vpnInfo = new VpnInfo();
6557 vpnInfo.ownerUid = vpnOwnerUid;
6558 mMockVpn.setVpnInfo(vpnInfo);
6559 }
6560
6561 private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
6562 throws Exception {
6563 setupConnectionOwnerUid(vpnOwnerUid, vpnType);
6564
6565 // Test as VPN app
6566 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6567 mServiceContext.setPermission(
6568 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
6569 }
6570
6571 private ConnectionInfo getTestConnectionInfo() throws Exception {
6572 return new ConnectionInfo(
6573 IPPROTO_TCP,
6574 new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
6575 new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
6576 }
6577
6578 @Test
6579 public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
6580 final int myUid = Process.myUid();
6581 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
6582
6583 try {
6584 mService.getConnectionOwnerUid(getTestConnectionInfo());
6585 fail("Expected SecurityException for non-VpnService app");
6586 } catch (SecurityException expected) {
6587 }
6588 }
6589
6590 @Test
6591 public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
6592 final int myUid = Process.myUid();
6593 setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
6594
6595 try {
6596 mService.getConnectionOwnerUid(getTestConnectionInfo());
6597 fail("Expected SecurityException for non-VpnService app");
6598 } catch (SecurityException expected) {
6599 }
6600 }
6601
6602 @Test
6603 public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
6604 final int myUid = Process.myUid();
6605 setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
6606
6607 // TODO: Test the returned UID
6608 mService.getConnectionOwnerUid(getTestConnectionInfo());
6609 }
6610
6611 @Test
6612 public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
6613 final int myUid = Process.myUid();
6614 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
6615 mServiceContext.setPermission(
6616 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6617
6618 // TODO: Test the returned UID
6619 mService.getConnectionOwnerUid(getTestConnectionInfo());
6620 }
6621
6622 @Test
6623 public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
6624 throws Exception {
6625 final int myUid = Process.myUid();
6626 setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
6627 mServiceContext.setPermission(
6628 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
6629
6630 // TODO: Test the returned UID
6631 mService.getConnectionOwnerUid(getTestConnectionInfo());
6632 }
6633
Qingxi Li7cf06622020-01-17 17:54:27 -08006634 private TestNetworkAgentWrapper establishVpn(
6635 LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006636 final TestNetworkAgentWrapper
6637 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
Qingxi Li7cf06622020-01-17 17:54:27 -08006638 vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006639 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6640 mMockVpn.connect();
6641 mMockVpn.setUids(vpnRange);
6642 vpnNetworkAgent.connect(true);
6643 waitForIdle();
6644 return vpnNetworkAgent;
6645 }
6646
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006647 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6648 final PackageInfo packageInfo = new PackageInfo();
paulhu86e23eb2019-11-05 18:05:05 +08006649 if (hasSystemPermission) {
6650 packageInfo.requestedPermissions = new String[] {
6651 CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
6652 packageInfo.requestedPermissionsFlags = new int[] {
6653 REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
6654 } else {
6655 packageInfo.requestedPermissions = new String[0];
6656 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006657 packageInfo.applicationInfo = new ApplicationInfo();
6658 packageInfo.applicationInfo.privateFlags = 0;
6659 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6660 UserHandle.getAppId(uid));
6661 return packageInfo;
6662 }
Cody Kesting63e4e002019-12-18 10:57:50 -08006663
6664 @Test
6665 public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
6666 final NetworkRequest request =
6667 new NetworkRequest(
6668 new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
6669 try {
6670 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006671 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006672 fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
6673 } catch (IllegalArgumentException expected) {
6674 }
6675 }
6676
Automerger Merge Worker7d66c262020-03-04 04:53:17 +00006677 private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
6678 InOrder inOrder = inOrder(mNetworkManagementService);
6679 for (int i = 0; i < routes.length; i++) {
6680 inOrder.verify(mNetworkManagementService).addRoute(eq(netId), eq(routes[i]));
6681 }
6682 }
6683
6684 private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
6685 InOrder inOrder = inOrder(mNetworkManagementService);
6686 for (int i = 0; i < routes.length; i++) {
6687 inOrder.verify(mNetworkManagementService).removeRoute(eq(netId), eq(routes[i]));
6688 }
6689 }
6690
Cody Kesting63e4e002019-12-18 10:57:50 -08006691 @Test
6692 public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
6693 final NetworkRequest wifiRequest =
6694 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
Cody Kesting63e4e002019-12-18 10:57:50 -08006695 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6696
6697 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006698 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006699
Cody Kestinge330fcd2020-01-15 16:31:08 -08006700 // Block until all other events are done processing.
6701 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6702
6703 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
6704 verify(mConnectivityDiagnosticsCallback).asBinder();
Cody Kesting63e4e002019-12-18 10:57:50 -08006705 assertTrue(
6706 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6707 mConnectivityDiagnosticsCallback));
6708
6709 mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
6710 verify(mIBinder, timeout(TIMEOUT_MS))
6711 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
6712 assertFalse(
6713 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6714 mConnectivityDiagnosticsCallback));
6715 verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
6716 }
6717
6718 @Test
6719 public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
6720 final NetworkRequest wifiRequest =
6721 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
6722 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6723
6724 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006725 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006726
Cody Kestinge330fcd2020-01-15 16:31:08 -08006727 // Block until all other events are done processing.
6728 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6729
6730 verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
Cody Kesting63e4e002019-12-18 10:57:50 -08006731 verify(mConnectivityDiagnosticsCallback).asBinder();
6732 assertTrue(
6733 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6734 mConnectivityDiagnosticsCallback));
6735
6736 // Register the same callback again
6737 mService.registerConnectivityDiagnosticsCallback(
Cody Kestinga75e26b2020-01-05 14:06:39 -08006738 mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
Cody Kesting63e4e002019-12-18 10:57:50 -08006739
6740 // Block until all other events are done processing.
6741 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6742
6743 assertTrue(
6744 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6745 mConnectivityDiagnosticsCallback));
6746 }
Cody Kestinga75e26b2020-01-05 14:06:39 -08006747
6748 @Test
6749 public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
6750 final NetworkAgentInfo naiWithoutUid =
6751 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006752 null, null, null, null, null, new NetworkCapabilities(), 0,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006753 mServiceContext, null, null, mService, null, null, null, 0);
6754
6755 mServiceContext.setPermission(
6756 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6757 assertTrue(
6758 "NetworkStack permission not applied",
6759 mService.checkConnectivityDiagnosticsPermissions(
6760 Process.myPid(), Process.myUid(), naiWithoutUid,
6761 mContext.getOpPackageName()));
6762 }
6763
6764 @Test
6765 public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
6766 final NetworkAgentInfo naiWithoutUid =
6767 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006768 null, null, null, null, null, new NetworkCapabilities(), 0,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006769 mServiceContext, null, null, mService, null, null, null, 0);
6770
6771 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6772
6773 assertFalse(
6774 "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics",
6775 mService.checkConnectivityDiagnosticsPermissions(
6776 Process.myPid(), Process.myUid(), naiWithoutUid,
6777 mContext.getOpPackageName()));
6778 }
6779
6780 @Test
6781 public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
6782 final NetworkAgentInfo naiWithoutUid =
6783 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006784 null, null, null, null, null, new NetworkCapabilities(), 0,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006785 mServiceContext, null, null, mService, null, null, null, 0);
6786
6787 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6788 Manifest.permission.ACCESS_FINE_LOCATION);
6789 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6790
6791 // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be
6792 // active
6793 final VpnInfo info = new VpnInfo();
6794 info.ownerUid = Process.myUid();
6795 info.vpnIface = "interface";
6796 mMockVpn.setVpnInfo(info);
6797 assertTrue(
6798 "Active VPN permission not applied",
6799 mService.checkConnectivityDiagnosticsPermissions(
6800 Process.myPid(), Process.myUid(), naiWithoutUid,
6801 mContext.getOpPackageName()));
6802 }
6803
6804 @Test
6805 public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
6806 final NetworkCapabilities nc = new NetworkCapabilities();
6807 nc.setAdministratorUids(Arrays.asList(Process.myUid()));
6808 final NetworkAgentInfo naiWithUid =
6809 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006810 null, null, null, null, null, nc, 0, mServiceContext, null, null,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006811 mService, null, null, null, 0);
6812
6813 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6814 Manifest.permission.ACCESS_FINE_LOCATION);
6815 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6816
6817 // Disconnect mock vpn so the uid check on NetworkAgentInfo is tested
6818 mMockVpn.disconnect();
6819 assertTrue(
6820 "NetworkCapabilities administrator uid permission not applied",
6821 mService.checkConnectivityDiagnosticsPermissions(
6822 Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName()));
6823 }
6824
6825 @Test
6826 public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
6827 final NetworkCapabilities nc = new NetworkCapabilities();
6828 nc.setOwnerUid(Process.myUid());
6829 nc.setAdministratorUids(Arrays.asList(Process.myUid()));
6830 final NetworkAgentInfo naiWithUid =
6831 new NetworkAgentInfo(
Automerger Merge Worker3d40f5782020-03-08 06:07:47 +00006832 null, null, null, null, null, nc, 0, mServiceContext, null, null,
Cody Kestinga75e26b2020-01-05 14:06:39 -08006833 mService, null, null, null, 0);
6834
6835 setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
6836 Manifest.permission.ACCESS_FINE_LOCATION);
6837 mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
6838
6839 // Use wrong pid and uid
6840 assertFalse(
6841 "Permissions allowed when they shouldn't be granted",
6842 mService.checkConnectivityDiagnosticsPermissions(
6843 Process.myPid() + 1, Process.myUid() + 1, naiWithUid,
6844 mContext.getOpPackageName()));
6845 }
6846
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006847 private void setUpConnectivityDiagnosticsCallback() throws Exception {
Cody Kestinga75e26b2020-01-05 14:06:39 -08006848 final NetworkRequest request = new NetworkRequest.Builder().build();
6849 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6850
6851 mServiceContext.setPermission(
6852 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
6853
6854 mService.registerConnectivityDiagnosticsCallback(
6855 mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
6856
6857 // Block until all other events are done processing.
6858 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6859
6860 // Connect the cell agent verify that it notifies TestNetworkCallback that it is available
6861 final TestNetworkCallback callback = new TestNetworkCallback();
6862 mCm.registerDefaultNetworkCallback(callback);
6863 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
6864 mCellNetworkAgent.connect(true);
6865 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
6866 callback.assertNoCallback();
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006867 }
6868
6869 @Test
6870 public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception {
6871 setUpConnectivityDiagnosticsCallback();
Cody Kestinga75e26b2020-01-05 14:06:39 -08006872
Cody Kestinge330fcd2020-01-15 16:31:08 -08006873 // Block until all other events are done processing.
6874 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6875
6876 // Verify onConnectivityReport fired
Cody Kestinga3b71c42020-02-11 10:03:26 -08006877 verify(mConnectivityDiagnosticsCallback).onConnectivityReport(
6878 argThat(report -> {
6879 final NetworkCapabilities nc = report.getNetworkCapabilities();
6880 return nc.getUids() == null
6881 && nc.getAdministratorUids().isEmpty()
6882 && nc.getOwnerUid() == Process.INVALID_UID;
6883 }));
Cody Kestinga75e26b2020-01-05 14:06:39 -08006884 }
Cody Kesting4f49f142020-01-06 16:55:35 -08006885
6886 @Test
6887 public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception {
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006888 setUpConnectivityDiagnosticsCallback();
Cody Kesting4f49f142020-01-06 16:55:35 -08006889
6890 // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the
6891 // cellular network agent
6892 mCellNetworkAgent.notifyDataStallSuspected();
6893
Cody Kestinge330fcd2020-01-15 16:31:08 -08006894 // Block until all other events are done processing.
6895 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6896
6897 // Verify onDataStallSuspected fired
Cody Kestinga3b71c42020-02-11 10:03:26 -08006898 verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(
6899 argThat(report -> {
6900 final NetworkCapabilities nc = report.getNetworkCapabilities();
6901 return nc.getUids() == null
6902 && nc.getAdministratorUids().isEmpty()
6903 && nc.getOwnerUid() == Process.INVALID_UID;
6904 }));
Cody Kesting4f49f142020-01-06 16:55:35 -08006905 }
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006906
6907 @Test
6908 public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
6909 setUpConnectivityDiagnosticsCallback();
6910
6911 final Network n = mCellNetworkAgent.getNetwork();
6912 final boolean hasConnectivity = true;
6913 mService.reportNetworkConnectivity(n, hasConnectivity);
6914
Cody Kestinge330fcd2020-01-15 16:31:08 -08006915 // Block until all other events are done processing.
6916 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6917
6918 // Verify onNetworkConnectivityReported fired
6919 verify(mConnectivityDiagnosticsCallback)
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006920 .onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
6921
6922 final boolean noConnectivity = false;
6923 mService.reportNetworkConnectivity(n, noConnectivity);
6924
Cody Kestinge330fcd2020-01-15 16:31:08 -08006925 // Block until all other events are done processing.
6926 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6927
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006928 // Wait for onNetworkConnectivityReported to fire
Cody Kestinge330fcd2020-01-15 16:31:08 -08006929 verify(mConnectivityDiagnosticsCallback)
Cody Kesting1e5ab9b2020-01-07 11:18:54 -08006930 .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
6931 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006932}