blob: 50f1bbeed0c5b14f629d915240349f7949325469 [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;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060079
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090080import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090081import static com.android.testutils.ConcurrentUtilsKt.await;
82import static com.android.testutils.ConcurrentUtilsKt.durationOf;
Chalard Jeane7b24752019-06-20 16:01:19 +090083import static com.android.testutils.ExceptionUtils.ignoreExceptions;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +090084import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
85import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
86import static com.android.testutils.MiscAssertsKt.assertEmpty;
87import static com.android.testutils.MiscAssertsKt.assertLength;
88import static com.android.testutils.MiscAssertsKt.assertRunsInAtMost;
89import static com.android.testutils.MiscAssertsKt.assertThrows;
90
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090091import static org.junit.Assert.assertEquals;
92import static org.junit.Assert.assertFalse;
junyulai4a192e22018-06-13 15:00:37 +080093import static org.junit.Assert.assertNotEquals;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090094import static org.junit.Assert.assertNotNull;
95import static org.junit.Assert.assertNull;
Jeff Sharkey72f9c422017-10-27 17:22:59 -060096import static org.junit.Assert.assertTrue;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090097import static org.junit.Assert.fail;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +090098import static org.mockito.ArgumentMatchers.anyLong;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +090099import static org.mockito.ArgumentMatchers.anyString;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000100import static org.mockito.ArgumentMatchers.eq;
Chalard Jean587758b2019-11-29 16:41:50 +0900101import static org.mockito.ArgumentMatchers.startsWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900102import static org.mockito.Matchers.anyInt;
Erik Klinee89953b2018-01-11 16:11:10 +0900103import static org.mockito.Mockito.any;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600104import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900105import static org.mockito.Mockito.doAnswer;
106import static org.mockito.Mockito.doNothing;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900107import static org.mockito.Mockito.doReturn;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000108import static org.mockito.Mockito.inOrder;
Jeff Sharkey3671b1e2013-01-31 17:22:26 -0800109import static org.mockito.Mockito.mock;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600110import static org.mockito.Mockito.never;
111import static org.mockito.Mockito.reset;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900112import static org.mockito.Mockito.spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900113import static org.mockito.Mockito.timeout;
Erik Klinee89953b2018-01-11 16:11:10 +0900114import static org.mockito.Mockito.times;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600115import static org.mockito.Mockito.verify;
Erik Kline79c6d052018-03-21 07:18:33 -0700116import static org.mockito.Mockito.verifyNoMoreInteractions;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900117import static org.mockito.Mockito.when;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700118
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900119import android.Manifest;
junyulai7c469172019-01-16 20:23:34 +0800120import android.annotation.NonNull;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900121import android.app.AlarmManager;
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900122import android.app.NotificationManager;
Paul Jensenbb2e0e92015-06-16 15:11:58 -0400123import android.app.PendingIntent;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400124import android.content.BroadcastReceiver;
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900125import android.content.ContentProvider;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900126import android.content.ContentResolver;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700127import android.content.Context;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400128import android.content.Intent;
129import android.content.IntentFilter;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000130import android.content.pm.ApplicationInfo;
131import android.content.pm.PackageInfo;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100132import android.content.pm.PackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000133import android.content.pm.UserInfo;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900134import android.content.res.Resources;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900135import android.net.CaptivePortalData;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400136import android.net.ConnectivityManager;
137import android.net.ConnectivityManager.NetworkCallback;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900138import android.net.ConnectivityManager.PacketKeepalive;
139import android.net.ConnectivityManager.PacketKeepaliveCallback;
Hugo Benichicb883232017-05-11 13:16:17 +0900140import android.net.ConnectivityManager.TooManyRequestsException;
Chalard Jeanb72b62d2018-02-16 16:08:35 +0900141import android.net.ConnectivityThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800142import android.net.IConnectivityDiagnosticsCallback;
Luke Huang65914772019-03-16 00:31:46 +0800143import android.net.IDnsResolver;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900144import android.net.IIpConnectivityMetrics;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800145import android.net.INetd;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900146import android.net.INetworkMonitor;
147import android.net.INetworkMonitorCallbacks;
Mike Yuf9729752018-08-17 15:22:05 +0800148import android.net.INetworkPolicyListener;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700149import android.net.INetworkPolicyManager;
150import android.net.INetworkStatsService;
junyulai4a192e22018-06-13 15:00:37 +0800151import android.net.InterfaceConfiguration;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900152import android.net.IpPrefix;
junyulai48eac1d42018-12-27 17:25:29 +0800153import android.net.IpSecManager;
154import android.net.IpSecManager.UdpEncapsulationSocket;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900155import android.net.LinkAddress;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700156import android.net.LinkProperties;
Etan Cohena7434272017-04-03 12:17:51 -0700157import android.net.MatchAllNetworkSpecifier;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400158import android.net.Network;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400159import android.net.NetworkCapabilities;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700160import android.net.NetworkFactory;
Chalard Jean9ca13772019-11-15 12:08:36 +0900161import android.net.NetworkInfo;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400162import android.net.NetworkRequest;
Etan Cohena7434272017-04-03 12:17:51 -0700163import android.net.NetworkSpecifier;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900164import android.net.NetworkStack;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900165import android.net.NetworkStackClient;
Varun Anandd33cbc62019-02-07 14:13:13 -0800166import android.net.NetworkState;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100167import android.net.NetworkUtils;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000168import android.net.ProxyInfo;
waynema13516842019-03-12 18:13:49 +0800169import android.net.ResolverParamsParcel;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700170import android.net.RouteInfo;
junyulai48eac1d42018-12-27 17:25:29 +0800171import android.net.SocketKeepalive;
Chalard Jean0b214af2018-01-12 17:22:49 +0900172import android.net.UidRange;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900173import android.net.Uri;
Hugo Benichif9fdf872016-07-28 17:53:06 +0900174import android.net.metrics.IpConnectivityLog;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900175import android.net.shared.NetworkMonitorUtils;
176import android.net.shared.PrivateDnsConfig;
Lorenzo Colitti58ebe1c2017-01-24 09:41:36 +0900177import android.net.util.MultinetworkPolicyTracker;
Chalard Jean751bb3f2019-06-19 23:29:58 +0900178import android.os.BadParcelableException;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100179import android.os.Binder;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900180import android.os.Bundle;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400181import android.os.ConditionVariable;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700182import android.os.Handler;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700183import android.os.HandlerThread;
Cody Kesting63e4e002019-12-18 10:57:50 -0800184import android.os.IBinder;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700185import android.os.INetworkManagementService;
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900186import android.os.Looper;
Etan Cohena7434272017-04-03 12:17:51 -0700187import android.os.Parcel;
junyulai0c666972019-03-04 22:45:36 +0800188import android.os.ParcelFileDescriptor;
Etan Cohena7434272017-04-03 12:17:51 -0700189import android.os.Parcelable;
Robin Leed2baf792016-03-24 12:07:00 +0000190import android.os.Process;
junyulai4a192e22018-06-13 15:00:37 +0800191import android.os.RemoteException;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900192import android.os.SystemClock;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900193import android.os.UserHandle;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000194import android.os.UserManager;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900195import android.provider.Settings;
junyulai0c666972019-03-04 22:45:36 +0800196import android.system.Os;
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900197import android.test.mock.MockContentResolver;
Etan Cohen836ad572018-12-30 17:59:59 -0800198import android.text.TextUtils;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100199import android.util.ArraySet;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700200import android.util.Log;
Etan Cohenddb720a2019-01-08 12:09:18 -0800201import android.util.SparseArray;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700202
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800203import androidx.test.InstrumentationRegistry;
Guang Zhub90866d2019-09-01 21:37:04 -0700204import androidx.test.filters.FlakyTest;
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800205import androidx.test.filters.SmallTest;
206import androidx.test.runner.AndroidJUnit4;
207
Chalard Jean587758b2019-11-29 16:41:50 +0900208import com.android.internal.app.IBatteryStats;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900209import com.android.internal.net.VpnConfig;
Varun Anandd33cbc62019-02-07 14:13:13 -0800210import com.android.internal.net.VpnInfo;
Erik Klinee89953b2018-01-11 16:11:10 +0900211import com.android.internal.util.ArrayUtils;
Lorenzo Colittibfecba22016-02-21 01:09:26 +0900212import com.android.internal.util.WakeupMessage;
Lorenzo Colitti3c295b52016-10-28 12:56:03 +0900213import com.android.internal.util.test.BroadcastInterceptingContext;
Lorenzo Colittib8df76e42016-10-28 12:37:38 +0900214import com.android.internal.util.test.FakeSettingsProvider;
Cody Kesting63e4e002019-12-18 10:57:50 -0800215import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
Chalard Jeandda156a2018-01-10 21:19:32 +0900216import com.android.server.connectivity.ConnectivityConstants;
Hugo Benichi64901e52017-10-19 14:42:40 +0900217import com.android.server.connectivity.DefaultNetworkMetrics;
218import com.android.server.connectivity.IpConnectivityMetrics;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900219import com.android.server.connectivity.MockableSystemProperties;
junyulai4a192e22018-06-13 15:00:37 +0800220import com.android.server.connectivity.Nat464Xlat;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900221import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000222import com.android.server.connectivity.ProxyTracker;
Chalard Jeandda156a2018-01-10 21:19:32 +0900223import com.android.server.connectivity.Vpn;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900224import com.android.server.net.NetworkPinner;
Hugo Benichi938ab4f2017-02-11 17:04:43 +0900225import com.android.server.net.NetworkPolicyManagerInternal;
Chalard Jeane7b24752019-06-20 16:01:19 +0900226import com.android.testutils.ExceptionUtils;
Chalard Jeance75e0e2019-05-28 16:48:32 +0900227import com.android.testutils.HandlerUtilsKt;
Chalard Jean059c4262019-09-30 17:51:12 +0900228import com.android.testutils.RecorderCallback.CallbackEntry;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900229import com.android.testutils.TestableNetworkCallback;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400230
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900231import org.junit.After;
232import org.junit.Before;
Hugo Benichi849b81b2017-05-25 13:42:31 +0900233import org.junit.Ignore;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900234import org.junit.Test;
235import org.junit.runner.RunWith;
Erik Klinee89953b2018-01-11 16:11:10 +0900236import org.mockito.ArgumentCaptor;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000237import org.mockito.InOrder;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900238import org.mockito.Mock;
239import org.mockito.MockitoAnnotations;
240import org.mockito.Spy;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900241import org.mockito.stubbing.Answer;
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900242
junyulai0c666972019-03-04 22:45:36 +0800243import java.io.IOException;
244import java.net.DatagramSocket;
junyulai4a192e22018-06-13 15:00:37 +0800245import java.net.Inet4Address;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000246import java.net.Inet6Address;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700247import java.net.InetAddress;
Xiao Maa4637112019-02-07 15:03:57 +0900248import java.net.InetSocketAddress;
249import java.net.Socket;
Paul Jensen4e1d3fd2016-04-08 13:56:52 -0400250import java.util.ArrayList;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +0900251import java.util.Arrays;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100252import java.util.Collection;
junyulai4a192e22018-06-13 15:00:37 +0800253import java.util.Collections;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900254import java.util.HashMap;
dalyk1fcb7392018-03-05 12:42:22 -0500255import java.util.HashSet;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100256import java.util.List;
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900257import java.util.Objects;
Rubin Xu1bb5c082017-09-05 18:40:49 +0100258import java.util.Set;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900259import java.util.concurrent.CountDownLatch;
junyulai48eac1d42018-12-27 17:25:29 +0800260import java.util.concurrent.Executor;
junyulai06835112019-01-03 18:50:15 +0800261import java.util.concurrent.ExecutorService;
junyulai48eac1d42018-12-27 17:25:29 +0800262import java.util.concurrent.Executors;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900263import java.util.concurrent.LinkedBlockingQueue;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900264import java.util.concurrent.TimeUnit;
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700265import java.util.concurrent.atomic.AtomicBoolean;
Chalard Jean9ca13772019-11-15 12:08:36 +0900266import java.util.function.Predicate;
Chalard Jean6f4216f2019-06-05 01:40:32 +0900267
268import kotlin.reflect.KClass;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700269
270/**
271 * Tests for {@link ConnectivityService}.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400272 *
273 * Build, install and run with:
Hugo Benichibb91c572017-05-22 10:44:02 +0900274 * runtest frameworks-net -c com.android.server.ConnectivityServiceTest
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700275 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900276@RunWith(AndroidJUnit4.class)
277@SmallTest
278public class ConnectivityServiceTest {
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700279 private static final String TAG = "ConnectivityServiceTest";
280
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900281 private static final int TIMEOUT_MS = 500;
Chalard Jeanb299b842019-09-27 17:13:14 +0900282 private static final int TEST_LINGER_DELAY_MS = 300;
Remi NGUYEN VANef8377d2018-07-26 16:39:45 +0900283 // Chosen to be less than the linger timeout. This ensures that we can distinguish between a
284 // LOST callback that arrives immediately and a LOST callback that arrives after the linger
285 // timeout. For this, our assertions should run fast enough to leave less than
286 // (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are
287 // supposedly fired, and the time we call expectCallback.
Chalard Jeanb299b842019-09-27 17:13:14 +0900288 private static final int TEST_CALLBACK_TIMEOUT_MS = 250;
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +0900289 // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to
290 // complete before callbacks are verified.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900291 private static final int TEST_REQUEST_TIMEOUT_MS = 150;
292
293 private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900294
junyulai4a192e22018-06-13 15:00:37 +0800295 private static final String CLAT_PREFIX = "v4-";
Erik Kline79c6d052018-03-21 07:18:33 -0700296 private static final String MOBILE_IFNAME = "test_rmnet_data0";
297 private static final String WIFI_IFNAME = "test_wlan0";
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200298 private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
Luke Huang65914772019-03-16 00:31:46 +0800299 private static final String[] EMPTY_STRING_ARRAY = new String[0];
Erik Kline79c6d052018-03-21 07:18:33 -0700300
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900301 private MockContext mServiceContext;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900302 private HandlerThread mCsHandlerThread;
303 private ConnectivityService mService;
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900304 private WrappedConnectivityManager mCm;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900305 private TestNetworkAgentWrapper mWiFiNetworkAgent;
306 private TestNetworkAgentWrapper mCellNetworkAgent;
307 private TestNetworkAgentWrapper mEthernetNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900308 private MockVpn mMockVpn;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900309 private Context mContext;
Mike Yuf9729752018-08-17 15:22:05 +0800310 private INetworkPolicyListener mPolicyListener;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900311 private WrappedMultinetworkPolicyTracker mPolicyTracker;
312 private HandlerThread mAlarmManagerThread;
Jeff Sharkeyfb878b62012-07-26 18:32:30 -0700313
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900314 @Mock IIpConnectivityMetrics mIpConnectivityMetrics;
Hugo Benichi64901e52017-10-19 14:42:40 +0900315 @Mock IpConnectivityMetrics.Logger mMetricsService;
316 @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
Erik Klinee89953b2018-01-11 16:11:10 +0900317 @Mock INetworkManagementService mNetworkManagementService;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600318 @Mock INetworkStatsService mStatsService;
Chalard Jean587758b2019-11-29 16:41:50 +0900319 @Mock IBatteryStats mBatteryStatsService;
Mike Yuf9729752018-08-17 15:22:05 +0800320 @Mock INetworkPolicyManager mNpm;
Luke Huang65914772019-03-16 00:31:46 +0800321 @Mock IDnsResolver mMockDnsResolver;
Chenbo Feng7f14dbc2018-11-08 17:36:21 -0800322 @Mock INetd mMockNetd;
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900323 @Mock NetworkStackClient mNetworkStack;
Rubin Xu9e64dc02019-04-23 18:04:14 +0100324 @Mock PackageManager mPackageManager;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000325 @Mock UserManager mUserManager;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900326 @Mock NotificationManager mNotificationManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900327 @Mock AlarmManager mAlarmManager;
Cody Kesting63e4e002019-12-18 10:57:50 -0800328 @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
329 @Mock IBinder mIBinder;
Hugo Benichi64901e52017-10-19 14:42:40 +0900330
waynema13516842019-03-12 18:13:49 +0800331 private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
332 ArgumentCaptor.forClass(ResolverParamsParcel.class);
Erik Klinee89953b2018-01-11 16:11:10 +0900333
Lorenzo Colitti531a3442016-03-01 12:55:58 +0900334 // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
335 // do not go through ConnectivityService but talk to netd directly, so they don't automatically
336 // reflect the state of our test ConnectivityService.
337 private class WrappedConnectivityManager extends ConnectivityManager {
338 private Network mFakeBoundNetwork;
339
340 public synchronized boolean bindProcessToNetwork(Network network) {
341 mFakeBoundNetwork = network;
342 return true;
343 }
344
345 public synchronized Network getBoundNetworkForProcess() {
346 return mFakeBoundNetwork;
347 }
348
349 public WrappedConnectivityManager(Context context, ConnectivityService service) {
350 super(context, service);
351 }
352 }
353
Paul Jensend7b6ca92015-05-13 14:05:12 -0400354 private class MockContext extends BroadcastInterceptingContext {
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900355 private final MockContentResolver mContentResolver;
Chalard Jean9ca13772019-11-15 12:08:36 +0900356 // Contains all registered receivers since this object was created. Useful to clear
357 // them when needed, as BroadcastInterceptingContext does not provide this facility.
358 private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>();
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900359
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900360 @Spy private Resources mResources;
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900361 private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900362 // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
363 private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900364
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900365 MockContext(Context base, ContentProvider settingsProvider) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400366 super(base);
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900367
368 mResources = spy(base.getResources());
369 when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
370 thenReturn(new String[] {
371 "wifi,1,1,1,-1,true",
372 "mobile,0,0,0,-1,true",
373 "mobile_mms,2,0,2,60000,true",
Chalard Jean9ca13772019-11-15 12:08:36 +0900374 "mobile_supl,3,0,2,60000,true",
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900375 });
376
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200377 when(mResources.getStringArray(
378 com.android.internal.R.array.config_wakeonlan_supported_interfaces))
379 .thenReturn(new String[]{
380 WIFI_WOL_IFNAME,
381 });
382
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900383 mContentResolver = new MockContentResolver();
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +0900384 mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400385 }
386
387 @Override
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900388 public void startActivityAsUser(Intent intent, UserHandle handle) {
389 mStartedActivities.offer(intent);
390 }
391
Chalard Jeanf30d1e12019-06-27 08:24:51 +0000392 public Intent expectStartActivityIntent(int timeoutMs) {
393 Intent intent = null;
394 try {
395 intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS);
396 } catch (InterruptedException e) {}
397 assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent);
398 return intent;
399 }
400
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +0900401 public void expectNoStartActivityIntent(int timeoutMs) {
402 try {
403 assertNull("Received unexpected Intent to start activity",
404 mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS));
405 } catch (InterruptedException e) {}
406 }
407
408 @Override
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900409 public Object getSystemService(String name) {
Lorenzo Colitti73b209382016-09-15 22:18:09 +0900410 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900411 if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900412 if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +0000413 if (Context.USER_SERVICE.equals(name)) return mUserManager;
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900414 if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400415 return super.getSystemService(name);
416 }
Lorenzo Colitti6d553f62016-06-05 02:20:29 +0900417
418 @Override
419 public ContentResolver getContentResolver() {
420 return mContentResolver;
421 }
Lorenzo Colitti42cdf572017-03-21 18:54:11 +0900422
423 @Override
424 public Resources getResources() {
425 return mResources;
426 }
Rubin Xu9e64dc02019-04-23 18:04:14 +0100427
428 @Override
429 public PackageManager getPackageManager() {
430 return mPackageManager;
431 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900432
433 @Override
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900434 public int checkPermission(String permission, int pid, int uid) {
435 final Integer granted = mMockedPermissions.get(permission);
436 if (granted == null) {
437 // All non-mocked permissions should be held by the test or unnecessary: check as
438 // normal to make sure the code does not rely on unexpected permissions.
439 return super.checkPermission(permission, pid, uid);
440 }
441 return granted;
442 }
443
444 @Override
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900445 public void enforceCallingOrSelfPermission(String permission, String message) {
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +0900446 final Integer granted = mMockedPermissions.get(permission);
447 if (granted == null) {
448 super.enforceCallingOrSelfPermission(permission, message);
449 return;
450 }
451
452 if (!granted.equals(PERMISSION_GRANTED)) {
453 throw new SecurityException("[Test] permission denied: " + permission);
454 }
455 }
456
457 /**
458 * Mock checks for the specified permission, and have them behave as per {@code granted}.
459 *
460 * <p>Passing null reverts to default behavior, which does a real permission check on the
461 * test package.
462 * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
463 * {@link PackageManager#PERMISSION_DENIED}.
464 */
465 public void setPermission(String permission, Integer granted) {
466 mMockedPermissions.put(permission, granted);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900467 }
Chalard Jean9ca13772019-11-15 12:08:36 +0900468
469 @Override
470 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
471 mRegisteredReceivers.add(receiver);
472 return super.registerReceiver(receiver, filter);
473 }
474
475 public void clearRegisteredReceivers() {
476 // super.unregisterReceiver is a no-op for receivers that are not registered (because
477 // they haven't been registered or because they have already been unregistered).
478 // For the same reason, don't bother clearing mRegisteredReceivers.
479 for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv);
480 }
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +0900481 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400482
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900483 private void waitForIdle() {
484 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
485 waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
486 waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS);
487 waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS);
488 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
489 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Hugo Benichibb91c572017-05-22 10:44:02 +0900490 }
491
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900492 private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900493 if (agent == null) {
494 return;
495 }
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900496 agent.waitForIdle(timeoutMs);
Hugo Benichibb91c572017-05-22 10:44:02 +0900497 }
498
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900499 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +0900500 public void testWaitForIdle() throws Exception {
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900501 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
502
503 // Tests that waitForIdle returns immediately if the service is already idle.
504 for (int i = 0; i < attempts; i++) {
Hugo Benichibb91c572017-05-22 10:44:02 +0900505 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900506 }
507
508 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900509 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900510 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900511 mWiFiNetworkAgent.connect(false);
512 waitFor(cv);
513 Network n = mWiFiNetworkAgent.getNetwork();
514 assertNotNull(n);
515
516 // Tests that calling waitForIdle waits for messages to be processed.
517 for (int i = 0; i < attempts; i++) {
518 mWiFiNetworkAgent.setSignalStrength(i);
Hugo Benichibb91c572017-05-22 10:44:02 +0900519 waitForIdle();
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900520 assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength());
521 }
Hugo Benichi5d540d12016-10-17 15:54:51 +0900522 }
523
Hugo Benichiad4db4e2016-10-17 15:54:51 +0900524 // This test has an inherent race condition in it, and cannot be enabled for continuous testing
525 // or presubmit tests. It is kept for manual runs and documentation purposes.
Andreas Gampe35dbf352018-01-26 20:41:17 -0800526 @Ignore
Chalard Jeane7b24752019-06-20 16:01:19 +0900527 public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
Hugo Benichi5d540d12016-10-17 15:54:51 +0900528 // Bring up a network that we can use to send messages to ConnectivityService.
Chalard Jean407deb72019-11-19 16:14:30 +0900529 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900530 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Hugo Benichi5d540d12016-10-17 15:54:51 +0900531 mWiFiNetworkAgent.connect(false);
532 waitFor(cv);
533 Network n = mWiFiNetworkAgent.getNetwork();
534 assertNotNull(n);
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900535
536 // Ensure that not calling waitForIdle causes a race condition.
Hugo Benichi5d540d12016-10-17 15:54:51 +0900537 final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng.
Lorenzo Colittie58961a2015-08-07 20:17:27 +0900538 for (int i = 0; i < attempts; i++) {
539 mWiFiNetworkAgent.setSignalStrength(i);
540 if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) {
541 // We hit a race condition, as expected. Pass the test.
542 return;
543 }
544 }
545
546 // No race? There is a bug in this test.
547 fail("expected race condition at least once in " + attempts + " attempts");
548 }
549
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900550 private class TestNetworkAgentWrapper extends NetworkAgentWrapper {
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800551 private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
552 | NETWORK_VALIDATION_PROBE_HTTP
553 | NETWORK_VALIDATION_PROBE_HTTPS;
554 private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
555 | NETWORK_VALIDATION_RESULT_VALID;
556 private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
557 | NETWORK_VALIDATION_PROBE_FALLBACK
558 | NETWORK_VALIDATION_RESULT_PARTIAL;
559 private static final int VALIDATION_RESULT_INVALID = 0;
560
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900561 private INetworkMonitor mNetworkMonitor;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900562 private INetworkMonitorCallbacks mNmCallbacks;
Chiachang Wang8ea15c962019-05-23 16:29:30 +0800563 private int mNmValidationResult = VALIDATION_RESULT_BASE;
lucaslin783f2212019-10-22 18:27:33 +0800564 private int mProbesCompleted;
565 private int mProbesSucceeded;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900566 private String mNmValidationRedirectUrl = null;
567 private boolean mNmProvNotificationRequested = false;
568
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900569 private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
570 // Contains the redirectUrl from networkStatus(). Before reading, wait for
571 // mNetworkStatusReceived.
572 private String mRedirectUrl;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900573
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900574 TestNetworkAgentWrapper(int transport) throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100575 this(transport, new LinkProperties());
576 }
577
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900578 TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
579 throws Exception {
580 super(transport, linkProperties, mServiceContext);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900581
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900582 // Waits for the NetworkAgent to be registered, which includes the creation of the
583 // NetworkMonitor.
584 waitForIdle(TIMEOUT_MS);
Chalard Jean3da8e0f2019-09-20 17:19:31 +0900585 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
586 HandlerUtilsKt.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900587 }
588
589 @Override
590 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
591 throws Exception {
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900592 mNetworkMonitor = mock(INetworkMonitor.class);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900593
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900594 final Answer validateAnswer = inv -> {
Chalard Jeane7b24752019-06-20 16:01:19 +0900595 new Thread(ignoreExceptions(this::onValidationRequested)).start();
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900596 return null;
597 };
598
Chalard Jeane7b24752019-06-20 16:01:19 +0900599 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
600 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900601
Remi NGUYEN VAN904a38b2019-03-15 02:25:09 +0900602 final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900603 final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
604 ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
605 doNothing().when(mNetworkStack).makeNetworkMonitor(
606 nmNetworkCaptor.capture(),
607 any() /* name */,
608 nmCbCaptor.capture());
609
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900610 final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
Paul Jensen232437312016-04-06 09:51:26 -0400611 @Override
612 public void networkStatus(int status, String redirectUrl) {
613 mRedirectUrl = redirectUrl;
614 mNetworkStatusReceived.open();
615 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400616 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900617
Chalard Jeanfe35bf92019-12-13 19:47:12 +0900618 assertEquals(na.network.netId, nmNetworkCaptor.getValue().netId);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900619 mNmCallbacks = nmCbCaptor.getValue();
620
Chalard Jeane7b24752019-06-20 16:01:19 +0900621 mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900622
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900623 return na;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900624 }
625
Chalard Jeane7b24752019-06-20 16:01:19 +0900626 private void onValidationRequested() throws Exception {
627 if (mNmProvNotificationRequested
628 && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
629 mNmCallbacks.hideProvisioningNotification();
630 mNmProvNotificationRequested = false;
631 }
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900632
lucaslin783f2212019-10-22 18:27:33 +0800633 mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
Chalard Jeane7b24752019-06-20 16:01:19 +0900634 mNmCallbacks.notifyNetworkTested(
635 mNmValidationResult, mNmValidationRedirectUrl);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900636
Chalard Jeane7b24752019-06-20 16:01:19 +0900637 if (mNmValidationRedirectUrl != null) {
638 mNmCallbacks.showProvisioningNotification(
639 "test_provisioning_notif_action", "com.android.test.package");
640 mNmProvNotificationRequested = true;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +0900641 }
Paul Jensen3d911462015-06-12 06:40:24 -0400642 }
643
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900644 /**
645 * Connect without adding any internet capability.
646 */
Paul Jensene0988542015-06-25 15:30:08 -0400647 public void connectWithoutInternet() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900648 super.connect();
Paul Jensene0988542015-06-25 15:30:08 -0400649 }
650
Paul Jensend7b6ca92015-05-13 14:05:12 -0400651 /**
Paul Jensene0988542015-06-25 15:30:08 -0400652 * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET.
Paul Jensend7b6ca92015-05-13 14:05:12 -0400653 * @param validated Indicate if network should pretend to be validated.
654 */
655 public void connect(boolean validated) {
lucaslin783f2212019-10-22 18:27:33 +0800656 connect(validated, true, false /* isStrictMode */);
Hugo Benichi16f0a942017-06-20 14:07:59 +0900657 }
658
659 /**
660 * Transition this NetworkAgent to CONNECTED state.
661 * @param validated Indicate if network should pretend to be validated.
662 * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
663 */
lucaslin783f2212019-10-22 18:27:33 +0800664 public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900665 assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
Paul Jensend7b6ca92015-05-13 14:05:12 -0400666
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900667 ConnectivityManager.NetworkCallback callback = null;
Paul Jensend7b6ca92015-05-13 14:05:12 -0400668 final ConditionVariable validatedCv = new ConditionVariable();
669 if (validated) {
lucaslin783f2212019-10-22 18:27:33 +0800670 setNetworkValid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400671 NetworkRequest request = new NetworkRequest.Builder()
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900672 .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
Chalard Jeanfb0c87e2018-04-18 19:18:58 +0900673 .clearCapabilities()
Paul Jensend7b6ca92015-05-13 14:05:12 -0400674 .build();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900675 callback = new ConnectivityManager.NetworkCallback() {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400676 public void onCapabilitiesChanged(Network network,
677 NetworkCapabilities networkCapabilities) {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400678 if (network.equals(getNetwork()) &&
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900679 networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
Paul Jensend7b6ca92015-05-13 14:05:12 -0400680 validatedCv.open();
681 }
682 }
683 };
Paul Jensencf4c2c62015-07-01 14:16:32 -0400684 mCm.registerNetworkCallback(request, callback);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400685 }
Hugo Benichi16f0a942017-06-20 14:07:59 +0900686 if (hasInternet) {
687 addCapability(NET_CAPABILITY_INTERNET);
688 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400689
Paul Jensene0988542015-06-25 15:30:08 -0400690 connectWithoutInternet();
Paul Jensend7b6ca92015-05-13 14:05:12 -0400691
692 if (validated) {
693 // Wait for network to validate.
Paul Jensen3d911462015-06-12 06:40:24 -0400694 waitFor(validatedCv);
lucaslin783f2212019-10-22 18:27:33 +0800695 setNetworkInvalid(isStrictMode);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400696 }
697
698 if (callback != null) mCm.unregisterNetworkCallback(callback);
699 }
700
lucaslin783f2212019-10-22 18:27:33 +0800701 public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
702 setNetworkPortal(redirectUrl, isStrictMode);
703 connect(false, true /* hasInternet */, isStrictMode);
Paul Jensencf4c2c62015-07-01 14:16:32 -0400704 }
705
lucasline252a742019-03-12 13:08:03 +0800706 public void connectWithPartialConnectivity() {
707 setNetworkPartial();
708 connect(false);
709 }
710
lucaslin783f2212019-10-22 18:27:33 +0800711 public void connectWithPartialValidConnectivity(boolean isStrictMode) {
712 setNetworkPartialValid(isStrictMode);
713 connect(false, true /* hasInternet */, isStrictMode);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +0900714 }
715
lucaslin783f2212019-10-22 18:27:33 +0800716 void setNetworkValid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900717 mNmValidationResult = VALIDATION_RESULT_VALID;
718 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800719 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP;
720 if (isStrictMode) {
721 probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
722 }
723 // The probesCompleted equals to probesSucceeded for the case of valid network, so put
724 // the same value into two different parameter of the method.
725 setProbesStatus(probesSucceeded, probesSucceeded);
Erik Kline1d3db322017-02-28 16:20:20 +0900726 }
727
lucaslin783f2212019-10-22 18:27:33 +0800728 void setNetworkInvalid(boolean isStrictMode) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900729 mNmValidationResult = VALIDATION_RESULT_INVALID;
730 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800731 int probesCompleted = VALIDATION_RESULT_BASE;
732 int probesSucceeded = VALIDATION_RESULT_INVALID;
733 // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
734 // tried to validate the private DNS but failed.
735 if (isStrictMode) {
736 probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
737 probesSucceeded = probesCompleted;
738 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
739 }
740 setProbesStatus(probesCompleted, probesSucceeded);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900741 }
742
lucaslin783f2212019-10-22 18:27:33 +0800743 void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
744 setNetworkInvalid(isStrictMode);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900745 mNmValidationRedirectUrl = redirectUrl;
lucaslin783f2212019-10-22 18:27:33 +0800746 // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
747 // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
748 int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
749 int probesSucceeded = VALIDATION_RESULT_INVALID;
750 if (isStrictMode) {
751 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
752 }
753 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400754 }
755
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900756 void setNetworkPartial() {
757 mNmValidationResult = VALIDATION_RESULT_PARTIAL;
758 mNmValidationRedirectUrl = null;
lucaslin783f2212019-10-22 18:27:33 +0800759 int probesCompleted = VALIDATION_RESULT_BASE;
760 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
761 setProbesStatus(probesCompleted, probesSucceeded);
Paul Jensend7b6ca92015-05-13 14:05:12 -0400762 }
Paul Jensene0988542015-06-25 15:30:08 -0400763
lucaslin783f2212019-10-22 18:27:33 +0800764 void setNetworkPartialValid(boolean isStrictMode) {
765 setNetworkPartial();
766 mNmValidationResult |= VALIDATION_RESULT_VALID;
767 int probesCompleted = VALIDATION_RESULT_BASE;
768 int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
769 // Suppose the partial network cannot pass the private DNS validation as well, so only
770 // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
771 if (isStrictMode) {
772 probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
773 }
774 setProbesStatus(probesCompleted, probesSucceeded);
775 }
776
777 void setProbesStatus(int probesCompleted, int probesSucceeded) {
778 mProbesCompleted = probesCompleted;
779 mProbesSucceeded = probesSucceeded;
Lorenzo Colitti7914ce52015-09-08 13:21:48 +0900780 }
Paul Jensen232437312016-04-06 09:51:26 -0400781
782 public String waitForRedirectUrl() {
783 assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
784 return mRedirectUrl;
785 }
Chalard Jean804b8fb2018-01-30 22:41:41 +0900786
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900787 public void expectDisconnected() {
788 expectDisconnected(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900789 }
790
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900791 public void expectPreventReconnectReceived() {
792 expectPreventReconnectReceived(TIMEOUT_MS);
Chalard Jean804b8fb2018-01-30 22:41:41 +0900793 }
Paul Jensend7b6ca92015-05-13 14:05:12 -0400794 }
795
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900796 /**
797 * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
798 * operations have been processed. Before ConnectivityService can add or remove any requests,
Chalard Jean05ab6812018-05-02 21:14:54 +0900799 * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900800 * expectRemoveRequests.
801 */
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700802 private static class MockNetworkFactory extends NetworkFactory {
Paul Jensencf4c2c62015-07-01 14:16:32 -0400803 private final ConditionVariable mNetworkStartedCV = new ConditionVariable();
804 private final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
Paul Jensencf4c2c62015-07-01 14:16:32 -0400805 private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700806
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900807 // Used to expect that requests be removed or added on a separate thread, without sleeping.
Chalard Jean05ab6812018-05-02 21:14:54 +0900808 // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
809 // once, then cause some other thread to add or remove requests, then call
810 // waitForRequests().
811 // It is not possible to wait for both add and remove requests. When adding, the queue
812 // contains the expected score. When removing, the value is unused, all matters is the
813 // number of objects in the queue.
814 private final LinkedBlockingQueue<Integer> mExpectations;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900815
816 // Whether we are currently expecting requests to be added or removed. Valid only if
Chalard Jean05ab6812018-05-02 21:14:54 +0900817 // mExpectations is non-empty.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900818 private boolean mExpectingAdditions;
819
Etan Cohenddb720a2019-01-08 12:09:18 -0800820 // Used to collect the networks requests managed by this factory. This is a duplicate of
821 // the internal information stored in the NetworkFactory (which is private).
822 private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
823
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700824 public MockNetworkFactory(Looper looper, Context context, String logTag,
825 NetworkCapabilities filter) {
826 super(looper, context, logTag, filter);
Chalard Jean05ab6812018-05-02 21:14:54 +0900827 mExpectations = new LinkedBlockingQueue<>();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700828 }
829
830 public int getMyRequestCount() {
831 return getRequestCount();
832 }
833
834 protected void startNetwork() {
835 mNetworkStarted.set(true);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400836 mNetworkStartedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700837 }
838
839 protected void stopNetwork() {
840 mNetworkStarted.set(false);
Paul Jensen0a2823e2015-06-12 10:31:09 -0400841 mNetworkStoppedCV.open();
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700842 }
843
844 public boolean getMyStartRequested() {
845 return mNetworkStarted.get();
846 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400847
848 public ConditionVariable getNetworkStartedCV() {
849 mNetworkStartedCV.close();
850 return mNetworkStartedCV;
851 }
852
853 public ConditionVariable getNetworkStoppedCV() {
854 mNetworkStoppedCV.close();
855 return mNetworkStoppedCV;
856 }
857
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900858 @Override
Chalard Jean05ab6812018-05-02 21:14:54 +0900859 protected void handleAddRequest(NetworkRequest request, int score,
860 int factorySerialNumber) {
861 synchronized (mExpectations) {
862 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900863
Chalard Jean05ab6812018-05-02 21:14:54 +0900864 assertNotNull("Added more requests than expected (" + request + " score : "
865 + score + ")", expectedScore);
866 // If we're expecting anything, we must be expecting additions.
867 if (!mExpectingAdditions) {
868 fail("Can't add requests while expecting requests to be removed");
869 }
870 if (expectedScore != score) {
871 fail("Expected score was " + expectedScore + " but actual was " + score
872 + " in added request");
873 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900874
Chalard Jean05ab6812018-05-02 21:14:54 +0900875 // Add the request.
876 mNetworkRequests.put(request.requestId, request);
877 super.handleAddRequest(request, score, factorySerialNumber);
878 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900879 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400880 }
881
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900882 @Override
883 protected void handleRemoveRequest(NetworkRequest request) {
Chalard Jean05ab6812018-05-02 21:14:54 +0900884 synchronized (mExpectations) {
885 final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900886
Chalard Jean05ab6812018-05-02 21:14:54 +0900887 assertTrue("Removed more requests than expected", expectedScore != null);
888 // If we're expecting anything, we must be expecting removals.
889 if (mExpectingAdditions) {
890 fail("Can't remove requests while expecting requests to be added");
891 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900892
Chalard Jean05ab6812018-05-02 21:14:54 +0900893 // Remove the request.
894 mNetworkRequests.remove(request.requestId);
895 super.handleRemoveRequest(request);
896 mExpectations.notify();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900897 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400898 }
899
Etan Cohenddb720a2019-01-08 12:09:18 -0800900 // Trigger releasing the request as unfulfillable
901 public void triggerUnfulfillable(NetworkRequest r) {
902 super.releaseRequestAsUnfulfillableByAnyFactory(r);
903 }
904
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900905 private void assertNoExpectations() {
Chalard Jean05ab6812018-05-02 21:14:54 +0900906 if (mExpectations.size() != 0) {
907 fail("Can't add expectation, " + mExpectations.size() + " already pending");
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900908 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400909 }
910
Chalard Jean05ab6812018-05-02 21:14:54 +0900911 // Expects that requests with the specified scores will be added.
912 public void expectAddRequestsWithScores(final int... scores) {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900913 assertNoExpectations();
914 mExpectingAdditions = true;
Chalard Jean05ab6812018-05-02 21:14:54 +0900915 for (int score : scores) {
916 mExpectations.add(score);
917 }
Paul Jensen0a2823e2015-06-12 10:31:09 -0400918 }
919
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900920 // Expects that count requests will be removed.
921 public void expectRemoveRequests(final int count) {
922 assertNoExpectations();
923 mExpectingAdditions = false;
Chalard Jean05ab6812018-05-02 21:14:54 +0900924 for (int i = 0; i < count; ++i) {
925 mExpectations.add(0); // For removals the score is ignored so any value will do.
926 }
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900927 }
928
929 // Waits for the expected request additions or removals to happen within a timeout.
930 public void waitForRequests() throws InterruptedException {
Chalard Jean05ab6812018-05-02 21:14:54 +0900931 final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
932 synchronized (mExpectations) {
933 while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
934 mExpectations.wait(deadline - SystemClock.elapsedRealtime());
935 }
936 }
937 final long count = mExpectations.size();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900938 final String msg = count + " requests still not " +
939 (mExpectingAdditions ? "added" : "removed") +
940 " after " + TIMEOUT_MS + " ms";
941 assertEquals(msg, 0, count);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900942 }
943
Etan Cohenddb720a2019-01-08 12:09:18 -0800944 public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
945 throws InterruptedException {
Lorenzo Colittiffa390b2015-08-08 01:55:44 +0900946 waitForRequests();
947 assertEquals(count, getMyRequestCount());
Etan Cohenddb720a2019-01-08 12:09:18 -0800948 return mNetworkRequests;
Paul Jensen0a2823e2015-06-12 10:31:09 -0400949 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -0700950 }
951
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900952 private static Looper startHandlerThreadAndReturnLooper() {
953 final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
954 handlerThread.start();
955 return handlerThread.getLooper();
956 }
957
958 private class MockVpn extends Vpn {
959 // TODO : the interactions between this mock and the mock network agent are too
960 // hard to get right at this moment, because it's unclear in which case which
961 // target needs to get a method call or both, and in what order. It's because
962 // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
963 // parent class of MockVpn agent wants that responsibility.
964 // That being said inside the test it should be possible to make the interactions
965 // harder to get wrong with precise speccing, judicious comments, helper methods
966 // and a few sprinkled assertions.
967
968 private boolean mConnected = false;
969 // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
970 // not inherit from NetworkAgent.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900971 private TestNetworkAgentWrapper mMockNetworkAgent;
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900972
973 public MockVpn(int userId) {
974 super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
975 userId);
976 }
977
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +0900978 public void setNetworkAgent(TestNetworkAgentWrapper agent) {
979 agent.waitForIdle(TIMEOUT_MS);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900980 mMockNetworkAgent = agent;
981 mNetworkAgent = agent.getNetworkAgent();
982 mNetworkCapabilities.set(agent.getNetworkCapabilities());
983 }
984
985 public void setUids(Set<UidRange> uids) {
986 mNetworkCapabilities.setUids(uids);
Varun Anand4fa80e82019-02-06 10:13:38 -0800987 updateCapabilities(null /* defaultNetwork */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900988 }
989
990 @Override
991 public int getNetId() {
Varun Anand4fa80e82019-02-06 10:13:38 -0800992 if (mMockNetworkAgent == null) {
993 return NETID_UNSET;
994 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +0900995 return mMockNetworkAgent.getNetwork().netId;
996 }
997
998 @Override
999 public boolean appliesToUid(int uid) {
1000 return mConnected; // Trickery to simplify testing.
1001 }
1002
1003 @Override
1004 protected boolean isCallerEstablishedOwnerLocked() {
1005 return mConnected; // Similar trickery
1006 }
1007
Varun Anandc51b06d2019-02-25 17:22:02 -08001008 private void connect(boolean isAlwaysMetered) {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001009 mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
1010 mConnected = true;
1011 mConfig = new VpnConfig();
Varun Anandc51b06d2019-02-25 17:22:02 -08001012 mConfig.isMetered = isAlwaysMetered;
1013 }
1014
1015 public void connectAsAlwaysMetered() {
1016 connect(true /* isAlwaysMetered */);
1017 }
1018
1019 public void connect() {
1020 connect(false /* isAlwaysMetered */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001021 }
1022
1023 @Override
Varun Anand4fa80e82019-02-06 10:13:38 -08001024 public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
1025 if (!mConnected) return null;
1026 super.updateCapabilities(defaultNetwork);
1027 // Because super.updateCapabilities will update the capabilities of the agent but
1028 // not the mock agent, the mock agent needs to know about them.
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001029 copyCapabilitiesToNetworkAgent();
Varun Anand4fa80e82019-02-06 10:13:38 -08001030 return new NetworkCapabilities(mNetworkCapabilities);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09001031 }
1032
1033 private void copyCapabilitiesToNetworkAgent() {
1034 if (null != mMockNetworkAgent) {
1035 mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
1036 false /* sendToConnectivityService */);
1037 }
1038 }
1039
1040 public void disconnect() {
1041 mConnected = false;
1042 mConfig = null;
1043 }
1044 }
1045
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001046 private void mockVpn(int uid) {
1047 synchronized (mService.mVpns) {
1048 int userId = UserHandle.getUserId(uid);
1049 mMockVpn = new MockVpn(userId);
1050 // This has no effect unless the VPN is actually connected, because things like
1051 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
1052 // netId, and check if that network is actually connected.
1053 mService.mVpns.put(userId, mMockVpn);
Lorenzo Colittibfecba22016-02-21 01:09:26 +09001054 }
1055 }
1056
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001057 private void setUidRulesChanged(int uidRules) throws RemoteException {
1058 mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
1059 }
Paul Jensencf4c2c62015-07-01 14:16:32 -04001060
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001061 private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException {
1062 mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
1063 }
1064
1065 private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) {
1066 return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
1067 }
1068
1069 private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
1070 volatile boolean mConfigRestrictsAvoidBadWifi;
1071 volatile int mConfigMeteredMultipathPreference;
1072
1073 WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
Erik Kline065ab6e2016-10-02 18:02:14 +09001074 super(c, h, r);
1075 }
1076
1077 @Override
1078 public boolean configRestrictsAvoidBadWifi() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001079 return mConfigRestrictsAvoidBadWifi;
Erik Kline065ab6e2016-10-02 18:02:14 +09001080 }
Lorenzo Colitti2de49252017-01-24 18:08:41 +09001081
1082 @Override
1083 public int configMeteredMultipathPreference() {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001084 return mConfigMeteredMultipathPreference;
Mike Yuf9729752018-08-17 15:22:05 +08001085 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001086 }
1087
Paul Jensen3d911462015-06-12 06:40:24 -04001088 /**
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09001089 * Wait up to TIMEOUT_MS for {@code conditionVariable} to open.
1090 * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
Paul Jensen3d911462015-06-12 06:40:24 -04001091 */
1092 static private void waitFor(ConditionVariable conditionVariable) {
Hugo Benichi16f0a942017-06-20 14:07:59 +09001093 if (conditionVariable.block(TIMEOUT_MS)) {
1094 return;
1095 }
1096 fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
Paul Jensen3d911462015-06-12 06:40:24 -04001097 }
1098
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001099 private static final int VPN_USER = 0;
1100 private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
1101 private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
1102 private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
1103
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001104 @Before
Paul Jensend7b6ca92015-05-13 14:05:12 -04001105 public void setUp() throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001106 mContext = InstrumentationRegistry.getContext();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001107
Hugo Benichi64901e52017-10-19 14:42:40 +09001108 MockitoAnnotations.initMocks(this);
1109 when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
1110
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001111 when(mUserManager.getUsers(eq(true))).thenReturn(
1112 Arrays.asList(new UserInfo[] {
1113 new UserInfo(VPN_USER, "", 0),
1114 }));
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00001115
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001116 // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
1117 // http://b/25897652 .
1118 if (Looper.myLooper() == null) {
1119 Looper.prepare();
1120 }
Rubin Xu9e64dc02019-04-23 18:04:14 +01001121 mockDefaultPackages();
Lorenzo Colitti2c1a2532015-11-27 10:52:10 +09001122
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001123 FakeSettingsProvider.clearSettingsProvider();
1124 mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
1125 new FakeSettingsProvider());
Hugo Benichi938ab4f2017-02-11 17:04:43 +09001126 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
1127 LocalServices.addService(
1128 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
Mike Yuf9729752018-08-17 15:22:05 +08001129
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001130 mAlarmManagerThread = new HandlerThread("TestAlarmManager");
1131 mAlarmManagerThread.start();
1132 initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
1133
1134 mCsHandlerThread = new HandlerThread("TestConnectivityService");
1135 final ConnectivityService.Dependencies deps = makeDependencies();
1136 mService = new ConnectivityService(mServiceContext,
Erik Klinee89953b2018-01-11 16:11:10 +09001137 mNetworkManagementService,
Jeff Sharkey72f9c422017-10-27 17:22:59 -06001138 mStatsService,
Mike Yuf9729752018-08-17 15:22:05 +08001139 mNpm,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001140 mMockDnsResolver,
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08001141 mock(IpConnectivityLog.class),
Luke Huang65914772019-03-16 00:31:46 +08001142 mMockNetd,
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001143 deps);
1144 mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
1145 verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001146
Mike Yuf9729752018-08-17 15:22:05 +08001147 final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
1148 ArgumentCaptor.forClass(INetworkPolicyListener.class);
1149 verify(mNpm).registerListener(policyListenerCaptor.capture());
1150 mPolicyListener = policyListenerCaptor.getValue();
1151
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001152 // Create local CM before sending system ready so that we can answer
1153 // getSystemService() correctly.
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001154 mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
Jeff Sharkeye0c29952018-02-20 17:24:55 -07001155 mService.systemReady();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001156 mockVpn(Process.myUid());
Lorenzo Colitti531a3442016-03-01 12:55:58 +09001157 mCm.bindProcessToNetwork(null);
Calvin On1f64f3f2016-10-11 15:10:46 -07001158
1159 // Ensure that the default setting for Captive Portals is used for most tests
1160 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001161 setAlwaysOnNetworks(false);
Erik Kline79c6d052018-03-21 07:18:33 -07001162 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Paul Jensend7b6ca92015-05-13 14:05:12 -04001163 }
1164
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001165 private ConnectivityService.Dependencies makeDependencies() {
1166 final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
1167 when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
1168 when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
1169
1170 final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
1171 doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
1172 doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
1173 doReturn(mNetworkStack).when(deps).getNetworkStack();
1174 doReturn(systemProperties).when(deps).getSystemProperties();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001175 doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
1176 doReturn(mMetricsService).when(deps).getMetricsLogger();
1177 doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
1178 doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
Chalard Jean587758b2019-11-29 16:41:50 +09001179 doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001180 doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
1181 doAnswer(inv -> {
1182 mPolicyTracker = new WrappedMultinetworkPolicyTracker(
1183 inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
1184 return mPolicyTracker;
1185 }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
1186
1187 return deps;
1188 }
1189
1190 private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
1191 doAnswer(inv -> {
1192 final long when = inv.getArgument(1);
1193 final WakeupMessage wakeupMsg = inv.getArgument(3);
1194 final Handler handler = inv.getArgument(4);
1195
1196 long delayMs = when - SystemClock.elapsedRealtime();
1197 if (delayMs < 0) delayMs = 0;
1198 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
1199 fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS
1200 + "ms into the future: " + delayMs);
1201 }
1202 alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */,
1203 delayMs);
1204
1205 return null;
1206 }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
1207 any(WakeupMessage.class), any());
1208
1209 doAnswer(inv -> {
1210 final WakeupMessage wakeupMsg = inv.getArgument(0);
1211 alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */);
1212 return null;
1213 }).when(am).cancel(any(WakeupMessage.class));
1214 }
1215
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001216 @After
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001217 public void tearDown() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07001218 setAlwaysOnNetworks(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001219 if (mCellNetworkAgent != null) {
1220 mCellNetworkAgent.disconnect();
1221 mCellNetworkAgent = null;
1222 }
1223 if (mWiFiNetworkAgent != null) {
1224 mWiFiNetworkAgent.disconnect();
1225 mWiFiNetworkAgent = null;
1226 }
1227 if (mEthernetNetworkAgent != null) {
1228 mEthernetNetworkAgent.disconnect();
1229 mEthernetNetworkAgent = null;
1230 }
Remi NGUYEN VAN91a1cc12018-09-28 14:33:11 +09001231 FakeSettingsProvider.clearSettingsProvider();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001232
1233 mCsHandlerThread.quitSafely();
1234 mAlarmManagerThread.quitSafely();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001235 }
1236
Rubin Xu9e64dc02019-04-23 18:04:14 +01001237 private void mockDefaultPackages() throws Exception {
1238 final String testPackageName = mContext.getPackageName();
1239 final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
1240 testPackageName, PackageManager.GET_PERMISSIONS);
1241 when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
1242 new String[] {testPackageName});
1243 when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
1244 eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
1245
1246 when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
1247 Arrays.asList(new PackageInfo[] {
1248 buildPackageInfo(/* SYSTEM */ false, APP1_UID),
1249 buildPackageInfo(/* SYSTEM */ false, APP2_UID),
1250 buildPackageInfo(/* SYSTEM */ false, VPN_UID)
1251 }));
1252 }
1253
Paul Jensend7b6ca92015-05-13 14:05:12 -04001254 private void verifyActiveNetwork(int transport) {
1255 // Test getActiveNetworkInfo()
1256 assertNotNull(mCm.getActiveNetworkInfo());
1257 assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
1258 // Test getActiveNetwork()
1259 assertNotNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001260 assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
Hugo Benichi16f0a942017-06-20 14:07:59 +09001261 if (!NetworkCapabilities.isValidTransport(transport)) {
1262 throw new IllegalStateException("Unknown transport " + transport);
1263 }
Paul Jensend7b6ca92015-05-13 14:05:12 -04001264 switch (transport) {
1265 case TRANSPORT_WIFI:
1266 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
1267 break;
1268 case TRANSPORT_CELLULAR:
1269 assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
1270 break;
1271 default:
Hugo Benichi16f0a942017-06-20 14:07:59 +09001272 break;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001273 }
1274 // Test getNetworkInfo(Network)
1275 assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
Hugo Benichibb91c572017-05-22 10:44:02 +09001276 assertEquals(transportToLegacyType(transport),
1277 mCm.getNetworkInfo(mCm.getActiveNetwork()).getType());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001278 // Test getNetworkCapabilities(Network)
1279 assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork()));
1280 assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport));
1281 }
1282
1283 private void verifyNoNetwork() {
Hugo Benichic1014502017-07-19 10:10:52 +09001284 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001285 // Test getActiveNetworkInfo()
1286 assertNull(mCm.getActiveNetworkInfo());
1287 // Test getActiveNetwork()
1288 assertNull(mCm.getActiveNetwork());
Robin Leed2baf792016-03-24 12:07:00 +00001289 assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
Paul Jensend7b6ca92015-05-13 14:05:12 -04001290 // Test getAllNetworks()
Hugo Benichifed512a2017-06-26 10:06:49 +09001291 assertEmpty(mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001292 }
1293
1294 /**
1295 * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
1296 * broadcasts are received.
1297 */
Chalard Jean407deb72019-11-19 16:14:30 +09001298 private ConditionVariable registerConnectivityBroadcast(final int count) {
1299 return registerConnectivityBroadcastThat(count, intent -> true);
Chalard Jean9ca13772019-11-15 12:08:36 +09001300 }
1301
Chalard Jean407deb72019-11-19 16:14:30 +09001302 private ConditionVariable registerConnectivityBroadcastThat(final int count,
Chalard Jean9ca13772019-11-15 12:08:36 +09001303 @NonNull final Predicate<Intent> filter) {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001304 final ConditionVariable cv = new ConditionVariable();
Chalard Jean9ca13772019-11-15 12:08:36 +09001305 final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
1306 intentFilter.addAction(CONNECTIVITY_ACTION_SUPL);
1307 final BroadcastReceiver receiver = new BroadcastReceiver() {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001308 private int remaining = count;
1309 public void onReceive(Context context, Intent intent) {
Chalard Jean9ca13772019-11-15 12:08:36 +09001310 if (!filter.test(intent)) return;
Paul Jensend7b6ca92015-05-13 14:05:12 -04001311 if (--remaining == 0) {
1312 cv.open();
1313 mServiceContext.unregisterReceiver(this);
1314 }
1315 }
Chalard Jean9ca13772019-11-15 12:08:36 +09001316 };
1317 mServiceContext.registerReceiver(receiver, intentFilter);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001318 return cv;
1319 }
1320
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001321 @Test
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001322 public void testNetworkTypes() {
1323 // Ensure that our mocks for the networkAttributes config variable work as expected. If they
1324 // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
1325 // will fail. Failing here is much easier to debug.
1326 assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
1327 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
Lorenzo Colitti7bbe3ee2017-08-24 22:35:10 +09001328 assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
1329 assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
1330
1331 // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
1332 // mocks, this assert exercises the ConnectivityService code path that ensures that
1333 // TYPE_ETHERNET is supported if the ethernet service is running.
1334 assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
Lorenzo Colitti42cdf572017-03-21 18:54:11 +09001335 }
1336
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001337 @Test
Chalard Jean9ca13772019-11-15 12:08:36 +09001338 public void testNetworkFeature() throws Exception {
1339 // Connect the cell agent and wait for the connected broadcast.
1340 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1341 mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
Chalard Jean407deb72019-11-19 16:14:30 +09001342 final ConditionVariable cv1 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001343 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE);
1344 mCellNetworkAgent.connect(true);
1345 waitFor(cv1);
1346
1347 // Build legacy request for SUPL.
1348 final NetworkCapabilities legacyCaps = new NetworkCapabilities();
1349 legacyCaps.addTransportType(TRANSPORT_CELLULAR);
1350 legacyCaps.addCapability(NET_CAPABILITY_SUPL);
1351 final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
1352 ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
1353
1354 // Send request and check that the legacy broadcast for SUPL is sent correctly.
1355 final TestNetworkCallback callback = new TestNetworkCallback();
Chalard Jean407deb72019-11-19 16:14:30 +09001356 final ConditionVariable cv2 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001357 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1358 mCm.requestNetwork(legacyRequest, callback);
1359 callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1360 waitFor(cv2);
1361
1362 // File another request, withdraw it and make sure no broadcast is sent
Chalard Jean407deb72019-11-19 16:14:30 +09001363 final ConditionVariable cv3 = registerConnectivityBroadcast(1);
Chalard Jean9ca13772019-11-15 12:08:36 +09001364 final TestNetworkCallback callback2 = new TestNetworkCallback();
1365 mCm.requestNetwork(legacyRequest, callback2);
1366 callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1367 mCm.unregisterNetworkCallback(callback2);
1368 assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent
1369 // As the broadcast did not fire, the receiver was not unregistered. Do this now.
1370 mServiceContext.clearRegisteredReceivers();
1371
1372 // Withdraw the request and check that the broadcast for disconnection is sent.
Chalard Jean407deb72019-11-19 16:14:30 +09001373 final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent ->
Chalard Jean9ca13772019-11-15 12:08:36 +09001374 !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected()
1375 && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1376 mCm.unregisterNetworkCallback(callback);
1377 waitFor(cv4);
1378
1379 // Re-file the request and expect the connected broadcast again
Chalard Jean407deb72019-11-19 16:14:30 +09001380 final ConditionVariable cv5 = registerConnectivityBroadcastThat(1,
Chalard Jean9ca13772019-11-15 12:08:36 +09001381 intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
1382 final TestNetworkCallback callback3 = new TestNetworkCallback();
1383 mCm.requestNetwork(legacyRequest, callback3);
1384 callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
1385 waitFor(cv5);
1386
1387 // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one
1388 // for mobile. Use a small hack to check that both have been sent, but the order is
1389 // not contractual.
1390 final AtomicBoolean vanillaAction = new AtomicBoolean(false);
1391 final AtomicBoolean suplAction = new AtomicBoolean(false);
Chalard Jean407deb72019-11-19 16:14:30 +09001392 final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> {
Chalard Jean9ca13772019-11-15 12:08:36 +09001393 if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
1394 vanillaAction.set(true);
1395 } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) {
1396 suplAction.set(true);
1397 }
1398 return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
1399 });
1400 mCellNetworkAgent.disconnect();
1401 waitFor(cv6);
1402 assertTrue(vanillaAction.get());
1403 assertTrue(suplAction.get());
1404 }
1405
1406 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001407 public void testLingering() throws Exception {
Paul Jensend7b6ca92015-05-13 14:05:12 -04001408 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001409 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1410 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001411 assertNull(mCm.getActiveNetworkInfo());
1412 assertNull(mCm.getActiveNetwork());
1413 // Test bringing up validated cellular.
Chalard Jean407deb72019-11-19 16:14:30 +09001414 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001415 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001416 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001417 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichifed512a2017-06-26 10:06:49 +09001418 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001419 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1420 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1421 assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
1422 mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
1423 // Test bringing up validated WiFi.
Chalard Jean407deb72019-11-19 16:14:30 +09001424 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001425 mWiFiNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001426 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001427 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001428 assertLength(2, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001429 assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
1430 mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
1431 assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
1432 mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
1433 // Test cellular linger timeout.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001434 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09001435 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09001436 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001437 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09001438 assertLength(1, mCm.getAllNetworks());
Paul Jensend7b6ca92015-05-13 14:05:12 -04001439 assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
1440 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001441 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001442 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001443 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001444 verifyNoNetwork();
1445 }
1446
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001447 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001448 public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
1449 // Test bringing up unvalidated WiFi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001450 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001451 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001452 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001453 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001454 verifyActiveNetwork(TRANSPORT_WIFI);
1455 // Test bringing up unvalidated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001456 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001457 mCellNetworkAgent.connect(false);
Hugo Benichibb91c572017-05-22 10:44:02 +09001458 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001459 verifyActiveNetwork(TRANSPORT_WIFI);
1460 // Test cellular disconnect.
1461 mCellNetworkAgent.disconnect();
Hugo Benichibb91c572017-05-22 10:44:02 +09001462 waitForIdle();
Paul Jensend7b6ca92015-05-13 14:05:12 -04001463 verifyActiveNetwork(TRANSPORT_WIFI);
1464 // Test bringing up validated cellular
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001465 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001466 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001467 mCellNetworkAgent.connect(true);
Paul Jensen3d911462015-06-12 06:40:24 -04001468 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001469 verifyActiveNetwork(TRANSPORT_CELLULAR);
1470 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001471 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001472 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001473 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001474 verifyActiveNetwork(TRANSPORT_WIFI);
1475 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001476 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001477 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001478 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001479 verifyNoNetwork();
1480 }
1481
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001482 @Test
Paul Jensend7b6ca92015-05-13 14:05:12 -04001483 public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
1484 // Test bringing up unvalidated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001485 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001486 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001487 mCellNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001488 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001489 verifyActiveNetwork(TRANSPORT_CELLULAR);
1490 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001491 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001492 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001493 mWiFiNetworkAgent.connect(false);
Paul Jensen3d911462015-06-12 06:40:24 -04001494 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001495 verifyActiveNetwork(TRANSPORT_WIFI);
1496 // Test WiFi disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001497 cv = registerConnectivityBroadcast(2);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001498 mWiFiNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001499 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001500 verifyActiveNetwork(TRANSPORT_CELLULAR);
1501 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001502 cv = registerConnectivityBroadcast(1);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001503 mCellNetworkAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04001504 waitFor(cv);
Paul Jensend7b6ca92015-05-13 14:05:12 -04001505 verifyNoNetwork();
1506 }
1507
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001508 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001509 public void testUnlingeringDoesNotValidate() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04001510 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001511 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001512 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001513 mWiFiNetworkAgent.connect(false);
Paul Jensene0988542015-06-25 15:30:08 -04001514 waitFor(cv);
1515 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001516 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001517 NET_CAPABILITY_VALIDATED));
Paul Jensencf4c2c62015-07-01 14:16:32 -04001518 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001519 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001520 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001521 mCellNetworkAgent.connect(true);
Paul Jensene0988542015-06-25 15:30:08 -04001522 waitFor(cv);
1523 verifyActiveNetwork(TRANSPORT_CELLULAR);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001524 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1525 NET_CAPABILITY_VALIDATED));
1526 // Test cellular disconnect.
Chalard Jean407deb72019-11-19 16:14:30 +09001527 cv = registerConnectivityBroadcast(2);
Paul Jensencf4c2c62015-07-01 14:16:32 -04001528 mCellNetworkAgent.disconnect();
1529 waitFor(cv);
1530 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001531 // Unlingering a network should not cause it to be marked as validated.
Paul Jensencf4c2c62015-07-01 14:16:32 -04001532 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
Paul Jensene0988542015-06-25 15:30:08 -04001533 NET_CAPABILITY_VALIDATED));
1534 }
1535
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001536 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001537 public void testCellularOutscoresWeakWifi() throws Exception {
1538 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001539 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001540 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001541 mCellNetworkAgent.connect(true);
1542 waitFor(cv);
1543 verifyActiveNetwork(TRANSPORT_CELLULAR);
1544 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001545 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001546 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001547 mWiFiNetworkAgent.connect(true);
1548 waitFor(cv);
1549 verifyActiveNetwork(TRANSPORT_WIFI);
1550 // Test WiFi getting really weak.
Chalard Jean407deb72019-11-19 16:14:30 +09001551 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001552 mWiFiNetworkAgent.adjustScore(-11);
1553 waitFor(cv);
1554 verifyActiveNetwork(TRANSPORT_CELLULAR);
1555 // Test WiFi restoring signal strength.
Chalard Jean407deb72019-11-19 16:14:30 +09001556 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001557 mWiFiNetworkAgent.adjustScore(11);
1558 waitFor(cv);
1559 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001560 }
1561
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001562 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001563 public void testReapingNetwork() throws Exception {
1564 // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
1565 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001566 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001567 mWiFiNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001568 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001569 // Test bringing up cellular without NET_CAPABILITY_INTERNET.
1570 // Expect it to be torn down immediately because it satisfies no requests.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001571 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001572 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001573 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001574 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001575 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001576 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001577 mWiFiNetworkAgent.connect(true);
1578 waitFor(cv);
1579 verifyActiveNetwork(TRANSPORT_WIFI);
1580 // Test bringing up unvalidated cellular.
1581 // Expect it to be torn down because it could never be the highest scoring network
1582 // satisfying the default request even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001583 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04001584 mCellNetworkAgent.connect(false);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001585 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001586 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001587 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001588 mWiFiNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04001589 }
1590
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001591 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001592 public void testCellularFallback() throws Exception {
1593 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001594 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001595 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001596 mCellNetworkAgent.connect(true);
1597 waitFor(cv);
1598 verifyActiveNetwork(TRANSPORT_CELLULAR);
1599 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001600 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001601 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001602 mWiFiNetworkAgent.connect(true);
1603 waitFor(cv);
1604 verifyActiveNetwork(TRANSPORT_WIFI);
1605 // Reevaluate WiFi (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001606 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001607 assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1608 NET_CAPABILITY_VALIDATED));
1609 mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
1610 // Should quickly fall back to Cellular.
1611 waitFor(cv);
1612 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1613 NET_CAPABILITY_VALIDATED));
1614 verifyActiveNetwork(TRANSPORT_CELLULAR);
1615 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001616 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001617 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1618 NET_CAPABILITY_VALIDATED));
1619 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1620 // Should quickly fall back to WiFi.
1621 waitFor(cv);
1622 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1623 NET_CAPABILITY_VALIDATED));
1624 assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
1625 NET_CAPABILITY_VALIDATED));
1626 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001627 }
1628
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001629 @Test
Paul Jensene0988542015-06-25 15:30:08 -04001630 public void testWiFiFallback() throws Exception {
1631 // Test bringing up unvalidated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001632 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09001633 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04001634 mWiFiNetworkAgent.connect(false);
1635 waitFor(cv);
1636 verifyActiveNetwork(TRANSPORT_WIFI);
1637 // Test bringing up validated cellular.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001638 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09001639 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001640 mCellNetworkAgent.connect(true);
1641 waitFor(cv);
1642 verifyActiveNetwork(TRANSPORT_CELLULAR);
1643 // Reevaluate cellular (it'll instantly fail DNS).
Chalard Jean407deb72019-11-19 16:14:30 +09001644 cv = registerConnectivityBroadcast(2);
Paul Jensene0988542015-06-25 15:30:08 -04001645 assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1646 NET_CAPABILITY_VALIDATED));
1647 mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
1648 // Should quickly fall back to WiFi.
1649 waitFor(cv);
1650 assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
1651 NET_CAPABILITY_VALIDATED));
1652 verifyActiveNetwork(TRANSPORT_WIFI);
Paul Jensene0988542015-06-25 15:30:08 -04001653 }
1654
Lorenzo Colittied3168e2019-01-23 17:54:08 +09001655 @Test
1656 public void testRequiresValidation() {
1657 assertTrue(NetworkMonitorUtils.isValidationRequired(
1658 mCm.getDefaultRequest().networkCapabilities));
1659 }
1660
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001661 /**
1662 * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
1663 * this class receives, by calling expectCallback() exactly once each time a callback is
1664 * received. assertNoCallback may be called at any time.
1665 */
Chalard Jean6f4216f2019-06-05 01:40:32 +09001666 private class TestNetworkCallback extends TestableNetworkCallback {
Chalard Jeanb299b842019-09-27 17:13:14 +09001667 TestNetworkCallback() {
1668 super(TEST_CALLBACK_TIMEOUT_MS);
1669 }
1670
Chalard Jean6f4216f2019-06-05 01:40:32 +09001671 @Override
1672 public void assertNoCallback() {
1673 // TODO: better support this use case in TestableNetworkCallback
1674 waitForIdle();
1675 assertNoCallback(0 /* timeout */);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001676 }
Paul Jensen3d911462015-06-12 06:40:24 -04001677
Erik Klineacdd6392016-07-07 16:50:58 +09001678 @Override
Chalard Jean059c4262019-09-30 17:51:12 +09001679 public <T extends CallbackEntry> T expectCallback(final KClass<T> type, final HasNetwork n,
Chalard Jean6f4216f2019-06-05 01:40:32 +09001680 final long timeoutMs) {
1681 final T callback = super.expectCallback(type, n, timeoutMs);
Chalard Jean059c4262019-09-30 17:51:12 +09001682 if (callback instanceof CallbackEntry.Losing) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09001683 // TODO : move this to the specific test(s) needing this rather than here.
Chalard Jean059c4262019-09-30 17:51:12 +09001684 final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback;
Chalard Jean6f4216f2019-06-05 01:40:32 +09001685 final int maxMsToLive = losing.getMaxMsToLive();
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001686 String msg = String.format(
1687 "Invalid linger time value %d, must be between %d and %d",
Chalard Jean6f4216f2019-06-05 01:40:32 +09001688 maxMsToLive, 0, mService.mLingerDelayMs);
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001689 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001690 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09001691 return callback;
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001692 }
1693 }
1694
1695 // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
1696 // only be declared in a static or top level type".
1697 static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
1698 for (TestNetworkCallback c : callbacks) {
1699 c.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001700 }
1701 }
1702
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001703 @Test
Paul Jensen3d911462015-06-12 06:40:24 -04001704 public void testStateChangeNetworkCallbacks() throws Exception {
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001705 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001706 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
1707 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001708 final NetworkRequest genericRequest = new NetworkRequest.Builder()
1709 .clearCapabilities().build();
Paul Jensen3d911462015-06-12 06:40:24 -04001710 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1711 .addTransportType(TRANSPORT_WIFI).build();
1712 final NetworkRequest cellRequest = new NetworkRequest.Builder()
1713 .addTransportType(TRANSPORT_CELLULAR).build();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001714 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001715 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
1716 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
1717
1718 // Test unvalidated networks
Chalard Jean407deb72019-11-19 16:14:30 +09001719 ConditionVariable cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001720 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001721 mCellNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001722 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1723 cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001724 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1725 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001726 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001727
Paul Jensen3d911462015-06-12 06:40:24 -04001728 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1729 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001730 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001731 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001732 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1733
Chalard Jean407deb72019-11-19 16:14:30 +09001734 cv = registerConnectivityBroadcast(2);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001735 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001736 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001737 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1738 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001739 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1740 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001741 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001742
Chalard Jean407deb72019-11-19 16:14:30 +09001743 cv = registerConnectivityBroadcast(2);
Paul Jensen3d911462015-06-12 06:40:24 -04001744 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001745 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1746 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti83fa2582015-08-07 12:49:01 +09001747 cellNetworkCallback.assertNoCallback();
Paul Jensen3d911462015-06-12 06:40:24 -04001748 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001749 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001750
Chalard Jean407deb72019-11-19 16:14:30 +09001751 cv = registerConnectivityBroadcast(1);
Paul Jensen3d911462015-06-12 06:40:24 -04001752 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001753 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1754 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001755 waitFor(cv);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001756 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001757
1758 // Test validated networks
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001759 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen3d911462015-06-12 06:40:24 -04001760 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001761 genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1762 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001763 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001764 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001765
Paul Jensen3d911462015-06-12 06:40:24 -04001766 // This should not trigger spurious onAvailable() callbacks, b/21762680.
1767 mCellNetworkAgent.adjustScore(-1);
Hugo Benichibb91c572017-05-22 10:44:02 +09001768 waitForIdle();
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001769 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001770 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1771
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001772 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen3d911462015-06-12 06:40:24 -04001773 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001774 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001775 genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001776 genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001777 wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001778 cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Paul Jensen3d911462015-06-12 06:40:24 -04001779 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001780 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001781
Paul Jensen3d911462015-06-12 06:40:24 -04001782 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001783 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1784 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001785 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001786
Paul Jensen3d911462015-06-12 06:40:24 -04001787 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001788 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
1789 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09001790 assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
Paul Jensen3d911462015-06-12 06:40:24 -04001791 }
1792
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09001793 private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
1794 final TestNetworkCallback callback = new TestNetworkCallback();
1795 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
1796 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
1797 .addTransportType(TRANSPORT_WIFI).build();
1798 mCm.registerNetworkCallback(wifiRequest, callback);
1799 mCm.registerDefaultNetworkCallback(defaultCallback);
1800
1801 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1802 mWiFiNetworkAgent.connect(false);
1803 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1804 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1805
1806 final LinkProperties newLp = new LinkProperties();
1807 final Uri capportUrl = Uri.parse("https://capport.example.com/api");
1808 final CaptivePortalData capportData = new CaptivePortalData.Builder()
1809 .setCaptive(true).build();
1810 newLp.setCaptivePortalApiUrl(capportUrl);
1811 newLp.setCaptivePortalData(capportData);
1812 mWiFiNetworkAgent.sendLinkProperties(newLp);
1813
1814 final Uri expectedCapportUrl = sanitized ? null : capportUrl;
1815 final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
1816 callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1817 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())
1818 && Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
1819 defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
1820 Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())
1821 && Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
1822
1823 final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
1824 assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
1825 assertEquals(expectedCapportData, lp.getCaptivePortalData());
1826 }
1827
1828 @Test
1829 public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
1830 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1831 PERMISSION_DENIED);
1832 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
1833 PERMISSION_DENIED);
1834 doNetworkCallbacksSanitizationTest(true /* sanitized */);
1835 }
1836
1837 @Test
1838 public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
1839 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1840 PERMISSION_GRANTED);
1841 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
1842 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1843 }
1844
1845 @Test
1846 public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
1847 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
1848 PERMISSION_DENIED);
1849 mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
1850 doNetworkCallbacksSanitizationTest(false /* sanitized */);
1851 }
1852
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001853 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09001854 public void testMultipleLingering() throws Exception {
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09001855 // This test would be flaky with the default 120ms timer: that is short enough that
1856 // lingered networks are torn down before assertions can be run. We don't want to mock the
1857 // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
1858 // in detecting races.
1859 mService.mLingerDelayMs = 300;
1860
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001861 NetworkRequest request = new NetworkRequest.Builder()
1862 .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
1863 .build();
1864 TestNetworkCallback callback = new TestNetworkCallback();
1865 mCm.registerNetworkCallback(request, callback);
1866
1867 TestNetworkCallback defaultCallback = new TestNetworkCallback();
1868 mCm.registerDefaultNetworkCallback(defaultCallback);
1869
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001870 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
1871 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
1872 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001873
1874 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1875 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1876 mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
1877
1878 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001879 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
1880 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001881 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001882 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001883
1884 mWiFiNetworkAgent.connect(true);
1885 // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
1886 // We then get LOSING when wifi validates and cell is outscored.
Lorenzo Colitti27334542018-01-12 16:22:21 +09001887 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001888 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001889 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001890 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001891 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001892 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001893 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001894
1895 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001896 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001897 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09001898 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09001899 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001900 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001901 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001902 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001903
1904 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001905 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
1906 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001907 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001908 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001909
1910 for (int i = 0; i < 4; i++) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001911 TestNetworkAgentWrapper oldNetwork, newNetwork;
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001912 if (i % 2 == 0) {
1913 mWiFiNetworkAgent.adjustScore(-15);
1914 oldNetwork = mWiFiNetworkAgent;
1915 newNetwork = mCellNetworkAgent;
1916 } else {
1917 mWiFiNetworkAgent.adjustScore(15);
1918 oldNetwork = mCellNetworkAgent;
1919 newNetwork = mWiFiNetworkAgent;
1920
1921 }
Chalard Jean059c4262019-09-30 17:51:12 +09001922 callback.expectCallback(CallbackEntry.LOSING, oldNetwork);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09001923 // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
1924 // longer lingering?
Lorenzo Colitti27334542018-01-12 16:22:21 +09001925 defaultCallback.expectAvailableCallbacksValidated(newNetwork);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001926 assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
1927 }
1928 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1929
1930 // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
1931 // if the network is still up.
1932 mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
Erik Kline1d3db322017-02-28 16:20:20 +09001933 // We expect a notification about the capabilities change, and nothing else.
1934 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
1935 defaultCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09001936 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001937 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001938
1939 // Wifi no longer satisfies our listen, which is for an unmetered network.
1940 // But because its score is 55, it's still up (and the default network).
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001941 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
1942
1943 // Disconnect our test networks.
1944 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001945 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001946 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001947 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001948 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001949 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001950 waitForIdle();
1951 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001952
1953 mCm.unregisterNetworkCallback(callback);
Hugo Benichibb91c572017-05-22 10:44:02 +09001954 waitForIdle();
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001955
1956 // Check that a network is only lingered or torn down if it would not satisfy a request even
1957 // if it validated.
1958 request = new NetworkRequest.Builder().clearCapabilities().build();
1959 callback = new TestNetworkCallback();
1960
1961 mCm.registerNetworkCallback(request, callback);
1962
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001963 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001964 mCellNetworkAgent.connect(false); // Score: 10
Lorenzo Colitti27334542018-01-12 16:22:21 +09001965 callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
1966 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001967 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001968 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001969
1970 // Bring up wifi with a score of 20.
1971 // Cell stays up because it would satisfy the default request if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001972 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001973 mWiFiNetworkAgent.connect(false); // Score: 20
Lorenzo Colitti27334542018-01-12 16:22:21 +09001974 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
1975 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001976 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001977 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001978
1979 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001980 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
1981 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001982 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001983 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001984 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001985
1986 // Bring up wifi with a score of 70.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09001987 // Cell is lingered because it would not satisfy any request, even if it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09001988 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001989 mWiFiNetworkAgent.adjustScore(50);
1990 mWiFiNetworkAgent.connect(false); // Score: 70
Lorenzo Colitti27334542018-01-12 16:22:21 +09001991 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09001992 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09001993 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001994 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09001995 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09001996
1997 // Tear down wifi.
1998 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09001999 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2000 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002001 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002002 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002003 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002004
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002005 // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
2006 // it's arguably correct to linger it, since it was the default network before it validated.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002007 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002008 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002009 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002010 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002011 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002012 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002013 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002014 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002015 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002016
2017 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002018 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2019 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002020 defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002021 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002022 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
2023 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002024 waitForIdle();
2025 assertEquals(null, mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002026
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002027 // If a network is lingering, and we add and remove a request from it, resume lingering.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002028 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002029 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002030 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2031 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002032 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002033 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002034 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002035 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2036 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002037 // TODO: Investigate sending validated before losing.
Chalard Jean059c4262019-09-30 17:51:12 +09002038 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09002039 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002040 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002041
2042 NetworkRequest cellRequest = new NetworkRequest.Builder()
2043 .addTransportType(TRANSPORT_CELLULAR).build();
2044 NetworkCallback noopCallback = new NetworkCallback();
2045 mCm.requestNetwork(cellRequest, noopCallback);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002046 // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
2047 // lingering?
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002048 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002049 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002050
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002051 // Similar to the above: lingering can start even after the lingered request is removed.
2052 // Disconnect wifi and switch to cell.
Lorenzo Colitti09e20212016-07-04 16:24:16 +09002053 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.expectAvailableCallbacksValidated(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002057 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002058
2059 // Cell is now the default network. Pin it with a cell-specific request.
2060 noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
2061 mCm.requestNetwork(cellRequest, noopCallback);
2062
2063 // Now connect wifi, and expect it to become the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002064 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002065 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002066 callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
2067 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002068 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002069 // The default request is lingering on cell, but nothing happens to cell, and we send no
2070 // callbacks for it, because it's kept up by cellRequest.
2071 callback.assertNoCallback();
2072 // Now unregister cellRequest and expect cell to start lingering.
2073 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002074 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002075
2076 // Let linger run its course.
2077 callback.assertNoCallback();
Remi NGUYEN VAN605f12d2018-07-11 18:17:06 +09002078 final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09002079 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs);
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002080
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002081 // Register a TRACK_DEFAULT request and check that it does not affect lingering.
2082 TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
2083 mCm.registerDefaultNetworkCallback(trackDefaultCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002084 trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002085 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002086 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002087 callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002088 callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002089 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002090 trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
2091 defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09002092 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002093
2094 // Let linger run its course.
Chalard Jean059c4262019-09-30 17:51:12 +09002095 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002096
Lorenzo Colittib57578ca2016-07-01 01:53:25 +09002097 // Clean up.
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002098 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002099 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2100 defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
2101 trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002102
2103 mCm.unregisterNetworkCallback(callback);
2104 mCm.unregisterNetworkCallback(defaultCallback);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002105 mCm.unregisterNetworkCallback(trackDefaultCallback);
2106 }
2107
paulhu86e23eb2019-11-05 18:05:05 +08002108 private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
2109 final String testPackageName = mContext.getPackageName();
2110 when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
2111 .thenReturn(buildPackageInfo(true, uid));
2112 mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
2113 }
2114
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002115 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002116 public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07002117 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08002118 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Chalard Jean1fa777d2018-02-16 16:07:53 +09002119 NetworkRequest request = new NetworkRequest.Builder()
2120 .clearCapabilities()
2121 .build();
2122 TestNetworkCallback callback = new TestNetworkCallback();
2123 mCm.registerNetworkCallback(request, callback);
2124
2125 TestNetworkCallback defaultCallback = new TestNetworkCallback();
2126 mCm.registerDefaultNetworkCallback(defaultCallback);
2127
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002128 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
2129 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002130
2131 mCellNetworkAgent.connect(true);
2132 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2133 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2134
2135 // Wifi comes up and cell lingers.
2136 mWiFiNetworkAgent.connect(true);
2137 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
2138 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002139 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002140 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2141
2142 // File a request for cellular, then release it.
2143 NetworkRequest cellRequest = new NetworkRequest.Builder()
2144 .addTransportType(TRANSPORT_CELLULAR).build();
2145 NetworkCallback noopCallback = new NetworkCallback();
2146 mCm.requestNetwork(cellRequest, noopCallback);
2147 mCm.unregisterNetworkCallback(noopCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09002148 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chalard Jean1fa777d2018-02-16 16:07:53 +09002149
2150 // Let linger run its course.
Chalard Jeanb72b62d2018-02-16 16:08:35 +09002151 callback.assertNoCallback();
Chalard Jean1fa777d2018-02-16 16:07:53 +09002152 final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
2153 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent,
2154 lingerTimeoutMs);
2155
2156 // Clean up.
2157 mCm.unregisterNetworkCallback(defaultCallback);
2158 mCm.unregisterNetworkCallback(callback);
2159 }
2160
2161 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002162 public void testExplicitlySelected() throws Exception {
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002163 NetworkRequest request = new NetworkRequest.Builder()
2164 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2165 .build();
2166 TestNetworkCallback callback = new TestNetworkCallback();
2167 mCm.registerNetworkCallback(request, callback);
2168
2169 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002170 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002171 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002172 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002173
2174 // Bring up unvalidated wifi with explicitlySelected=true.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002175 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002176 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002177 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002178 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002179
2180 // Cell Remains the default.
2181 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2182
2183 // Lower wifi's score to below than cell, and check that it doesn't disconnect because
2184 // it's explicitly selected.
2185 mWiFiNetworkAgent.adjustScore(-40);
2186 mWiFiNetworkAgent.adjustScore(40);
2187 callback.assertNoCallback();
2188
2189 // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
2190 // wifi even though it's unvalidated.
2191 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002192 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002193 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2194
2195 // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
2196 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002197 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002198 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002199 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002200 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002201 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002202
2203 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
2204 // network to disconnect.
2205 mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
Chalard Jean059c4262019-09-30 17:51:12 +09002206 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002207
2208 // Reconnect, again with explicitlySelected=true, but this time validate.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002209 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002210 mWiFiNetworkAgent.explicitlySelected(true, false);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002211 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002212 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002213 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002214 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2215 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2216
2217 // BUG: the network will no longer linger, even though it's validated and outscored.
2218 // TODO: fix this.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002219 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002220 mEthernetNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002221 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002222 assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2223 callback.assertNoCallback();
2224
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002225 // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
2226 // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
2227 // wifi immediately.
2228 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002229 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002230 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002231 mWiFiNetworkAgent.explicitlySelected(true, true);
2232 mWiFiNetworkAgent.connect(false);
2233 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002234 callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002235 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2236 mEthernetNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002237 callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002238
2239 // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
2240 // Check that the network is not scored specially and that the device prefers cell data.
2241 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002242 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002243 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002244 mWiFiNetworkAgent.explicitlySelected(false, true);
2245 mWiFiNetworkAgent.connect(false);
2246 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2247 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2248
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002249 // Clean up.
2250 mWiFiNetworkAgent.disconnect();
2251 mCellNetworkAgent.disconnect();
Lorenzo Colitti02cc8392017-05-17 01:28:09 +09002252
Chalard Jean059c4262019-09-30 17:51:12 +09002253 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2254 callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti7369d8d12016-06-28 21:28:28 +09002255 }
2256
Chalard Jean05ab6812018-05-02 21:14:54 +09002257 private int[] makeIntArray(final int size, final int value) {
2258 final int[] array = new int[size];
2259 Arrays.fill(array, value);
2260 return array;
2261 }
2262
Paul Jensen85cf78e2015-06-25 13:25:07 -04002263 private void tryNetworkFactoryRequests(int capability) throws Exception {
Paul Jensen487ffe72015-07-24 15:57:11 -04002264 // Verify NOT_RESTRICTED is set appropriately
2265 final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
2266 .build().networkCapabilities;
2267 if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
2268 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
2269 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
Paul Jensenaae613d2015-08-19 11:06:15 -04002270 capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
Paul Jensen487ffe72015-07-24 15:57:11 -04002271 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2272 } else {
2273 assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
2274 }
2275
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002276 NetworkCapabilities filter = new NetworkCapabilities();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002277 filter.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002278 final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
2279 handlerThread.start();
Paul Jensen0a2823e2015-06-12 10:31:09 -04002280 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002281 mServiceContext, "testFactory", filter);
2282 testFactory.setScoreFilter(40);
Paul Jensen0a2823e2015-06-12 10:31:09 -04002283 ConditionVariable cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002284 testFactory.expectAddRequestsWithScores(0);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002285 testFactory.register();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002286 testFactory.waitForNetworkRequests(1);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002287 int expectedRequestCount = 1;
2288 NetworkCallback networkCallback = null;
2289 // For non-INTERNET capabilities we cannot rely on the default request being present, so
2290 // add one.
2291 if (capability != NET_CAPABILITY_INTERNET) {
Paul Jensen85cf78e2015-06-25 13:25:07 -04002292 assertFalse(testFactory.getMyStartRequested());
2293 NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
2294 networkCallback = new NetworkCallback();
Chalard Jean05ab6812018-05-02 21:14:54 +09002295 testFactory.expectAddRequestsWithScores(0); // New request
Paul Jensen85cf78e2015-06-25 13:25:07 -04002296 mCm.requestNetwork(request, networkCallback);
2297 expectedRequestCount++;
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002298 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002299 }
Paul Jensen3d911462015-06-12 06:40:24 -04002300 waitFor(cv);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002301 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2302 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002303
Paul Jensen85cf78e2015-06-25 13:25:07 -04002304 // Now bring in a higher scored network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002305 TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002306 // Rather than create a validated network which complicates things by registering it's
2307 // own NetworkRequest during startup, just bump up the score to cancel out the
2308 // unvalidated penalty.
2309 testAgent.adjustScore(40);
2310 cv = testFactory.getNetworkStoppedCV();
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002311
2312 // When testAgent connects, ConnectivityService will re-send us all current requests with
2313 // the new score. There are expectedRequestCount such requests, and we must wait for all of
2314 // them.
Chalard Jean05ab6812018-05-02 21:14:54 +09002315 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
Paul Jensen85cf78e2015-06-25 13:25:07 -04002316 testAgent.connect(false);
2317 testAgent.addCapability(capability);
Paul Jensen3d911462015-06-12 06:40:24 -04002318 waitFor(cv);
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002319 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002320 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002321
Paul Jensen85cf78e2015-06-25 13:25:07 -04002322 // Bring in a bunch of requests.
Chalard Jean05ab6812018-05-02 21:14:54 +09002323 testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002324 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002325 ConnectivityManager.NetworkCallback[] networkCallbacks =
2326 new ConnectivityManager.NetworkCallback[10];
2327 for (int i = 0; i< networkCallbacks.length; i++) {
2328 networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
2329 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002330 builder.addCapability(capability);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002331 mCm.requestNetwork(builder.build(), networkCallbacks[i]);
2332 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002333 testFactory.waitForNetworkRequests(10 + expectedRequestCount);
2334 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002335
Paul Jensen85cf78e2015-06-25 13:25:07 -04002336 // Remove the requests.
Lorenzo Colittiffa390b2015-08-08 01:55:44 +09002337 testFactory.expectRemoveRequests(10);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002338 for (int i = 0; i < networkCallbacks.length; i++) {
2339 mCm.unregisterNetworkCallback(networkCallbacks[i]);
2340 }
Paul Jensen85cf78e2015-06-25 13:25:07 -04002341 testFactory.waitForNetworkRequests(expectedRequestCount);
2342 assertFalse(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002343
Paul Jensen85cf78e2015-06-25 13:25:07 -04002344 // Drop the higher scored network.
2345 cv = testFactory.getNetworkStartedCV();
Chalard Jean05ab6812018-05-02 21:14:54 +09002346 // With the default network disconnecting, the requests are sent with score 0 to factories.
2347 testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002348 testAgent.disconnect();
Paul Jensen3d911462015-06-12 06:40:24 -04002349 waitFor(cv);
Chalard Jean05ab6812018-05-02 21:14:54 +09002350 testFactory.waitForNetworkRequests(expectedRequestCount);
Paul Jensen85cf78e2015-06-25 13:25:07 -04002351 assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
2352 assertTrue(testFactory.getMyStartRequested());
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002353
2354 testFactory.unregister();
Paul Jensen85cf78e2015-06-25 13:25:07 -04002355 if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback);
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002356 handlerThread.quit();
2357 }
2358
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002359 @Test
Paul Jensen85cf78e2015-06-25 13:25:07 -04002360 public void testNetworkFactoryRequests() throws Exception {
2361 tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
2362 tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
2363 tryNetworkFactoryRequests(NET_CAPABILITY_DUN);
2364 tryNetworkFactoryRequests(NET_CAPABILITY_FOTA);
2365 tryNetworkFactoryRequests(NET_CAPABILITY_IMS);
2366 tryNetworkFactoryRequests(NET_CAPABILITY_CBS);
2367 tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P);
2368 tryNetworkFactoryRequests(NET_CAPABILITY_IA);
2369 tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
2370 tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
2371 tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
2372 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
2373 tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
2374 tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
2375 tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
2376 // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
2377 }
2378
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002379 @Test
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002380 public void testNoMutableNetworkRequests() throws Exception {
2381 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
Hugo Benichi16f0a942017-06-20 14:07:59 +09002382 NetworkRequest request1 = new NetworkRequest.Builder()
2383 .addCapability(NET_CAPABILITY_VALIDATED)
2384 .build();
2385 NetworkRequest request2 = new NetworkRequest.Builder()
2386 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
2387 .build();
2388
2389 Class<IllegalArgumentException> expected = IllegalArgumentException.class;
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09002390 assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback()));
2391 assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent));
2392 assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback()));
2393 assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent));
Paul Jensenbb2e0e92015-06-16 15:11:58 -04002394 }
Robert Greenwalt348e98d2015-06-05 17:55:36 -07002395
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002396 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002397 public void testMMSonWiFi() throws Exception {
2398 // Test bringing up cellular without MMS NetworkRequest gets reaped
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002399 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002400 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002401 mCellNetworkAgent.connectWithoutInternet();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002402 mCellNetworkAgent.expectDisconnected();
Hugo Benichibb91c572017-05-22 10:44:02 +09002403 waitForIdle();
Hugo Benichifed512a2017-06-26 10:06:49 +09002404 assertEmpty(mCm.getAllNetworks());
Paul Jensene0988542015-06-25 15:30:08 -04002405 verifyNoNetwork();
Hugo Benichibb91c572017-05-22 10:44:02 +09002406
Paul Jensene0988542015-06-25 15:30:08 -04002407 // Test bringing up validated WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002408 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09002409 final ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002410 mWiFiNetworkAgent.connect(true);
2411 waitFor(cv);
2412 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002413
Paul Jensene0988542015-06-25 15:30:08 -04002414 // Register MMS NetworkRequest
2415 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2416 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2417 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2418 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002419
Paul Jensene0988542015-06-25 15:30:08 -04002420 // Test bringing up unvalidated cellular with MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002421 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002422 mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
Paul Jensene0988542015-06-25 15:30:08 -04002423 mCellNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002424 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002425 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichibb91c572017-05-22 10:44:02 +09002426
Paul Jensene0988542015-06-25 15:30:08 -04002427 // Test releasing NetworkRequest disconnects cellular with MMS
Paul Jensene0988542015-06-25 15:30:08 -04002428 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002429 mCellNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002430 verifyActiveNetwork(TRANSPORT_WIFI);
2431 }
2432
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002433 @Test
Paul Jensene0988542015-06-25 15:30:08 -04002434 public void testMMSonCell() throws Exception {
2435 // Test bringing up cellular without MMS
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002436 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean407deb72019-11-19 16:14:30 +09002437 ConditionVariable cv = registerConnectivityBroadcast(1);
Paul Jensene0988542015-06-25 15:30:08 -04002438 mCellNetworkAgent.connect(false);
2439 waitFor(cv);
2440 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002441
Paul Jensene0988542015-06-25 15:30:08 -04002442 // Register MMS NetworkRequest
2443 NetworkRequest.Builder builder = new NetworkRequest.Builder();
2444 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
2445 final TestNetworkCallback networkCallback = new TestNetworkCallback();
2446 mCm.requestNetwork(builder.build(), networkCallback);
Hugo Benichibb91c572017-05-22 10:44:02 +09002447
Paul Jensene0988542015-06-25 15:30:08 -04002448 // Test bringing up MMS cellular network
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002449 TestNetworkAgentWrapper
2450 mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Paul Jensene0988542015-06-25 15:30:08 -04002451 mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
2452 mmsNetworkAgent.connectWithoutInternet();
Lorenzo Colitti27334542018-01-12 16:22:21 +09002453 networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
Paul Jensene0988542015-06-25 15:30:08 -04002454 verifyActiveNetwork(TRANSPORT_CELLULAR);
Hugo Benichibb91c572017-05-22 10:44:02 +09002455
Paul Jensene0988542015-06-25 15:30:08 -04002456 // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
Paul Jensene0988542015-06-25 15:30:08 -04002457 mCm.unregisterNetworkCallback(networkCallback);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002458 mmsNetworkAgent.expectDisconnected();
Paul Jensene0988542015-06-25 15:30:08 -04002459 verifyActiveNetwork(TRANSPORT_CELLULAR);
2460 }
2461
lucaslinf3b59b32019-03-26 17:49:49 +08002462 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002463 public void testPartialConnectivity() throws Exception {
lucasline252a742019-03-12 13:08:03 +08002464 // Register network callback.
2465 NetworkRequest request = new NetworkRequest.Builder()
2466 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
2467 .build();
2468 TestNetworkCallback callback = new TestNetworkCallback();
2469 mCm.registerNetworkCallback(request, callback);
2470
2471 // Bring up validated mobile data.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002472 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
lucasline252a742019-03-12 13:08:03 +08002473 mCellNetworkAgent.connect(true);
2474 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
2475
2476 // Bring up wifi with partial connectivity.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002477 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002478 mWiFiNetworkAgent.connectWithPartialConnectivity();
2479 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2480 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2481
2482 // Mobile data should be the default network.
2483 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2484 callback.assertNoCallback();
2485
lucaslinf3b59b32019-03-26 17:49:49 +08002486 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
2487 // probe.
lucaslin783f2212019-10-22 18:27:33 +08002488 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
lucasline252a742019-03-12 13:08:03 +08002489 // If the user chooses yes to use this partial connectivity wifi, switch the default
2490 // network to wifi and check if wifi becomes valid or not.
2491 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2492 false /* always */);
lucaslinf3b59b32019-03-26 17:49:49 +08002493 // If user accepts partial connectivity network,
2494 // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
lucasline252a742019-03-12 13:08:03 +08002495 waitForIdle();
Chalard Jeane7b24752019-06-20 16:01:19 +09002496 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002497
lucaslinf3b59b32019-03-26 17:49:49 +08002498 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2499 // validated.
2500 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002501 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002502 NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
2503 mWiFiNetworkAgent);
2504 assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
2505 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2506
2507 // Disconnect and reconnect wifi with partial connectivity again.
2508 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002509 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002510 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002511 mWiFiNetworkAgent.connectWithPartialConnectivity();
2512 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2513 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
2514
2515 // Mobile data should be the default network.
2516 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2517
2518 // If the user chooses no, disconnect wifi immediately.
2519 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
2520 false /* always */);
Chalard Jean059c4262019-09-30 17:51:12 +09002521 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002522
2523 // If user accepted partial connectivity before, and device reconnects to that network
2524 // again, but now the network has full connectivity. The network shouldn't contain
2525 // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002526 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
lucasline252a742019-03-12 13:08:03 +08002527 // acceptUnvalidated is also used as setting for accepting partial networks.
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002528 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2529 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002530 mWiFiNetworkAgent.connect(true);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002531
lucaslinf3b59b32019-03-26 17:49:49 +08002532 // If user accepted partial connectivity network before,
2533 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2534 // ConnectivityService#updateNetworkInfo().
lucasline252a742019-03-12 13:08:03 +08002535 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002536 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002537 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002538 nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2539 assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002540
lucasline252a742019-03-12 13:08:03 +08002541 // Wifi should be the default network.
2542 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
2543 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002544 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002545
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002546 // The user accepted partial connectivity and selected "don't ask again". Now the user
2547 // reconnects to the partial connectivity network. Switch to wifi as soon as partial
2548 // connectivity is detected.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002549 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002550 mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
2551 true /* acceptUnvalidated */);
lucasline252a742019-03-12 13:08:03 +08002552 mWiFiNetworkAgent.connectWithPartialConnectivity();
lucaslinf3b59b32019-03-26 17:49:49 +08002553 // If user accepted partial connectivity network before,
2554 // NetworkMonitor#setAcceptPartialConnectivity() will be called in
2555 // ConnectivityService#updateNetworkInfo().
lucaslinf3b59b32019-03-26 17:49:49 +08002556 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002557 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002558 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002559 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
lucaslinf3b59b32019-03-26 17:49:49 +08002560 callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
lucaslin783f2212019-10-22 18:27:33 +08002561 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002562
lucaslinf3b59b32019-03-26 17:49:49 +08002563 // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
2564 // validated.
2565 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
2566 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2567 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002568 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002569
2570 // If the user accepted partial connectivity, and the device auto-reconnects to the partial
2571 // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002572 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002573 mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
2574 true /* acceptUnvalidated */);
2575
2576 // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
2577 // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
2578 // notifyNetworkConnected.
lucaslin783f2212019-10-22 18:27:33 +08002579 mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002580 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
lucaslinfe39f0a2019-09-04 18:14:22 +08002581 verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
Chalard Jean059c4262019-09-30 17:51:12 +09002582 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Lorenzo Colittib5ad6132019-06-04 22:15:33 +09002583 callback.expectCapabilitiesWith(
2584 NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
2585 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002586 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
lucasline252a742019-03-12 13:08:03 +08002587 }
2588
2589 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002590 public void testCaptivePortalOnPartialConnectivity() throws Exception {
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002591 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2592 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2593 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2594 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2595
2596 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2597 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2598 .addCapability(NET_CAPABILITY_VALIDATED).build();
2599 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2600
2601 // Bring up a network with a captive portal.
2602 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002603 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002604 String redirectUrl = "http://android.com/path";
lucaslin783f2212019-10-22 18:27:33 +08002605 mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002606 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002607 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002608
2609 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
2610 mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
2611 verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
2612 .launchCaptivePortalApp();
2613
2614 // Report that the captive portal is dismissed with partial connectivity, and check that
2615 // callbacks are fired.
2616 mWiFiNetworkAgent.setNetworkPartial();
Chiachang Wangf6d10b02019-05-24 11:20:47 +08002617 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002618 waitForIdle();
2619 captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2620 mWiFiNetworkAgent);
2621
2622 // Report partial connectivity is accepted.
lucaslin783f2212019-10-22 18:27:33 +08002623 mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002624 mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
2625 false /* always */);
2626 waitForIdle();
2627 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002628 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wang8ea15c962019-05-23 16:29:30 +08002629 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
2630 NetworkCapabilities nc =
2631 validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
2632 mWiFiNetworkAgent);
2633
2634 mCm.unregisterNetworkCallback(captivePortalCallback);
2635 mCm.unregisterNetworkCallback(validatedCallback);
2636 }
2637
2638 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002639 public void testCaptivePortal() throws Exception {
Paul Jensencf4c2c62015-07-01 14:16:32 -04002640 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2641 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2642 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2643 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2644
2645 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2646 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2647 .addCapability(NET_CAPABILITY_VALIDATED).build();
2648 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002649
2650 // Bring up a network with a captive portal.
2651 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002652 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002653 String firstRedirectUrl = "http://example.com/firstPath";
lucaslin783f2212019-10-22 18:27:33 +08002654 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002655 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002656 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002657
2658 // Take down network.
2659 // Expect onLost callback.
Paul Jensencf4c2c62015-07-01 14:16:32 -04002660 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09002661 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002662
2663 // Bring up a network with a captive portal.
2664 // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002665 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Paul Jensen232437312016-04-06 09:51:26 -04002666 String secondRedirectUrl = "http://example.com/secondPath";
lucaslin783f2212019-10-22 18:27:33 +08002667 mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002668 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Paul Jensen232437312016-04-06 09:51:26 -04002669 assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002670
2671 // Make captive portal disappear then revalidate.
2672 // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
lucaslin783f2212019-10-22 18:27:33 +08002673 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002674 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
Chalard Jean059c4262019-09-30 17:51:12 +09002675 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002676
2677 // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
Lorenzo Colitti27334542018-01-12 16:22:21 +09002678 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002679 // Expect no notification to be shown when captive portal disappears by itself
2680 verify(mNotificationManager, never()).notifyAsUser(
2681 anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
Paul Jensencf4c2c62015-07-01 14:16:32 -04002682
2683 // Break network connectivity.
2684 // Expect NET_CAPABILITY_VALIDATED onLost callback.
lucaslin783f2212019-10-22 18:27:33 +08002685 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002686 mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
Chalard Jean059c4262019-09-30 17:51:12 +09002687 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Paul Jensencf4c2c62015-07-01 14:16:32 -04002688 }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09002689
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002690 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002691 public void testCaptivePortalApp() throws Exception {
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002692 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2693 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2694 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2695 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2696
2697 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2698 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2699 .addCapability(NET_CAPABILITY_VALIDATED).build();
2700 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2701
2702 // Bring up wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002703 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002704 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002705 validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002706 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
2707
2708 // Check that calling startCaptivePortalApp does nothing.
2709 final int fastTimeoutMs = 100;
2710 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002711 waitForIdle();
2712 verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp();
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002713 mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
2714
2715 // Turn into a captive portal.
lucaslin783f2212019-10-22 18:27:33 +08002716 mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002717 mCm.reportNetworkConnectivity(wifiNetwork, false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002718 captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002719 validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002720
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002721 // Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002722 mCm.startCaptivePortalApp(wifiNetwork);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002723 waitForIdle();
2724 verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp();
2725
2726 // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal)
2727 final Bundle testBundle = new Bundle();
2728 final String testKey = "testkey";
2729 final String testValue = "testvalue";
2730 testBundle.putString(testKey, testValue);
Remi NGUYEN VANead1ef42019-12-17 16:45:42 +09002731 mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
2732 PERMISSION_GRANTED);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002733 mCm.startCaptivePortalApp(wifiNetwork, testBundle);
2734 final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
2735 assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
2736 assertEquals(testValue, signInIntent.getStringExtra(testKey));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002737
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002738 // Report that the captive portal is dismissed, and check that callbacks are fired
lucaslin783f2212019-10-22 18:27:33 +08002739 mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09002740 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
Lorenzo Colitti27334542018-01-12 16:22:21 +09002741 validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09002742 captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Remi NGUYEN VAN0839a192019-06-17 11:28:27 +09002743 verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
2744 eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
Lorenzo Colitti4734cdb2017-04-27 14:30:21 +09002745
2746 mCm.unregisterNetworkCallback(validatedCallback);
2747 mCm.unregisterNetworkCallback(captivePortalCallback);
2748 }
2749
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002750 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002751 public void testAvoidOrIgnoreCaptivePortals() throws Exception {
Calvin On1f64f3f2016-10-11 15:10:46 -07002752 final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
2753 final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
2754 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
2755 mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
2756
2757 final TestNetworkCallback validatedCallback = new TestNetworkCallback();
2758 final NetworkRequest validatedRequest = new NetworkRequest.Builder()
2759 .addCapability(NET_CAPABILITY_VALIDATED).build();
2760 mCm.registerNetworkCallback(validatedRequest, validatedCallback);
2761
2762 setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
2763 // Bring up a network with a captive portal.
2764 // Expect it to fail to connect and not result in any callbacks.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002765 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Calvin On1f64f3f2016-10-11 15:10:46 -07002766 String firstRedirectUrl = "http://example.com/firstPath";
2767
lucaslin783f2212019-10-22 18:27:33 +08002768 mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002769 mWiFiNetworkAgent.expectDisconnected();
2770 mWiFiNetworkAgent.expectPreventReconnectReceived();
Calvin On1f64f3f2016-10-11 15:10:46 -07002771
2772 assertNoCallbacks(captivePortalCallback, validatedCallback);
Calvin On1f64f3f2016-10-11 15:10:46 -07002773 }
2774
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002775 private NetworkRequest.Builder newWifiRequestBuilder() {
2776 return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
2777 }
2778
Etan Cohen836ad572018-12-30 17:59:59 -08002779 /**
2780 * Verify request matching behavior with network specifiers.
2781 *
2782 * Note: this test is somewhat problematic since it involves removing capabilities from
2783 * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
2784 * as a WTF bug in
2785 * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
2786 * does work.
2787 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002788 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002789 public void testNetworkSpecifier() throws Exception {
Etan Cohen836ad572018-12-30 17:59:59 -08002790 // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
2791 class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
2792 Parcelable {
2793 @Override
2794 public boolean satisfiedBy(NetworkSpecifier other) {
2795 return true;
2796 }
2797
2798 @Override
2799 public int describeContents() {
2800 return 0;
2801 }
2802
2803 @Override
2804 public void writeToParcel(Parcel dest, int flags) {}
2805
2806 @Override
2807 public NetworkSpecifier redact() {
2808 return null;
2809 }
2810 }
2811
2812 // A network specifier that matches either another LocalNetworkSpecifier with the same
2813 // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
2814 class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2815 private String mString;
2816
2817 LocalStringNetworkSpecifier(String string) {
2818 mString = string;
2819 }
2820
2821 @Override
2822 public boolean satisfiedBy(NetworkSpecifier other) {
2823 if (other instanceof LocalStringNetworkSpecifier) {
2824 return TextUtils.equals(mString,
2825 ((LocalStringNetworkSpecifier) other).mString);
2826 }
2827 if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
2828 return false;
2829 }
2830
2831 @Override
2832 public int describeContents() {
2833 return 0;
2834 }
2835 @Override
2836 public void writeToParcel(Parcel dest, int flags) {}
2837 }
2838
2839
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002840 NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
Etan Cohena7434272017-04-03 12:17:51 -07002841 NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002842 NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
Etan Cohena7434272017-04-03 12:17:51 -07002843 NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
2844 (NetworkSpecifier) null).build();
Etan Cohen836ad572018-12-30 17:59:59 -08002845 NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
2846 new LocalStringNetworkSpecifier("foo")).build();
Etan Cohena7434272017-04-03 12:17:51 -07002847 NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
Etan Cohen836ad572018-12-30 17:59:59 -08002848 new LocalStringNetworkSpecifier("bar")).build();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002849
2850 TestNetworkCallback cEmpty1 = new TestNetworkCallback();
2851 TestNetworkCallback cEmpty2 = new TestNetworkCallback();
2852 TestNetworkCallback cEmpty3 = new TestNetworkCallback();
Etan Cohena7434272017-04-03 12:17:51 -07002853 TestNetworkCallback cEmpty4 = new TestNetworkCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002854 TestNetworkCallback cFoo = new TestNetworkCallback();
2855 TestNetworkCallback cBar = new TestNetworkCallback();
2856 TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
Etan Cohen836ad572018-12-30 17:59:59 -08002857 cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002858
2859 mCm.registerNetworkCallback(rEmpty1, cEmpty1);
2860 mCm.registerNetworkCallback(rEmpty2, cEmpty2);
2861 mCm.registerNetworkCallback(rEmpty3, cEmpty3);
Etan Cohena7434272017-04-03 12:17:51 -07002862 mCm.registerNetworkCallback(rEmpty4, cEmpty4);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002863 mCm.registerNetworkCallback(rFoo, cFoo);
2864 mCm.registerNetworkCallback(rBar, cBar);
2865
Etan Cohen836ad572018-12-30 17:59:59 -08002866 LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
2867 LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
2868
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002869 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002870 mWiFiNetworkAgent.connect(false);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002871 cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2872 cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2873 cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2874 cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002875 assertNoCallbacks(cFoo, cBar);
2876
Etan Cohen836ad572018-12-30 17:59:59 -08002877 mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002878 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002879 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002880 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2881 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002882 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002883 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2884 (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
Etan Cohen836ad572018-12-30 17:59:59 -08002885 assertEquals(nsFoo,
2886 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002887 cFoo.assertNoCallback();
2888
Etan Cohen836ad572018-12-30 17:59:59 -08002889 mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
Chalard Jean059c4262019-09-30 17:51:12 +09002890 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09002891 cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002892 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002893 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2894 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002895 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002896 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2897 (caps) -> caps.getNetworkSpecifier().equals(nsBar));
Etan Cohen836ad572018-12-30 17:59:59 -08002898 assertEquals(nsBar,
2899 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2900 cBar.assertNoCallback();
2901
2902 mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
2903 cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
2904 for (TestNetworkCallback c : emptyCallbacks) {
Chalard Jean6f4216f2019-06-05 01:40:32 +09002905 c.expectCapabilitiesThat(mWiFiNetworkAgent,
2906 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002907 }
Chalard Jean6f4216f2019-06-05 01:40:32 +09002908 cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
2909 (caps) -> caps.getNetworkSpecifier() == null);
2910 cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
2911 (caps) -> caps.getNetworkSpecifier() == null);
Etan Cohen836ad572018-12-30 17:59:59 -08002912 assertNull(
2913 mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
2914 cFoo.assertNoCallback();
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002915 cBar.assertNoCallback();
2916
2917 mWiFiNetworkAgent.setNetworkSpecifier(null);
Chalard Jean059c4262019-09-30 17:51:12 +09002918 cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
2919 cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002920 for (TestNetworkCallback c: emptyCallbacks) {
Chalard Jean059c4262019-09-30 17:51:12 +09002921 c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002922 }
2923
Etan Cohen836ad572018-12-30 17:59:59 -08002924 assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
Lorenzo Colitti6556a222017-04-03 17:46:35 +09002925 }
2926
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002927 @Test
Etan Cohenddb9ef02015-11-18 10:56:15 -08002928 public void testInvalidNetworkSpecifier() {
Chalard Jean751bb3f2019-06-19 23:29:58 +09002929 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002930 NetworkRequest.Builder builder = new NetworkRequest.Builder();
Etan Cohena7434272017-04-03 12:17:51 -07002931 builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
Chalard Jean751bb3f2019-06-19 23:29:58 +09002932 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002933
Chalard Jean751bb3f2019-06-19 23:29:58 +09002934 assertThrows(IllegalArgumentException.class, () -> {
Etan Cohenddb9ef02015-11-18 10:56:15 -08002935 NetworkCapabilities networkCapabilities = new NetworkCapabilities();
2936 networkCapabilities.addTransportType(TRANSPORT_WIFI)
Etan Cohena7434272017-04-03 12:17:51 -07002937 .setNetworkSpecifier(new MatchAllNetworkSpecifier());
Etan Cohenddb9ef02015-11-18 10:56:15 -08002938 mService.requestNetwork(networkCapabilities, null, 0, null,
2939 ConnectivityManager.TYPE_WIFI);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002940 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002941
Etan Cohena7434272017-04-03 12:17:51 -07002942 class NonParcelableSpecifier extends NetworkSpecifier {
2943 public boolean satisfiedBy(NetworkSpecifier other) { return false; }
2944 };
2945 class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
2946 @Override public int describeContents() { return 0; }
2947 @Override public void writeToParcel(Parcel p, int flags) {}
2948 }
Etan Cohena7434272017-04-03 12:17:51 -07002949
Chalard Jean751bb3f2019-06-19 23:29:58 +09002950 final NetworkRequest.Builder builder =
2951 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
2952 assertThrows(ClassCastException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002953 builder.setNetworkSpecifier(new NonParcelableSpecifier());
2954 Parcel parcelW = Parcel.obtain();
2955 builder.build().writeToParcel(parcelW, 0);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002956 });
Etan Cohena7434272017-04-03 12:17:51 -07002957
Chalard Jean751bb3f2019-06-19 23:29:58 +09002958 final NetworkRequest nr =
2959 new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET)
2960 .setNetworkSpecifier(new ParcelableSpecifier())
2961 .build();
Etan Cohena7434272017-04-03 12:17:51 -07002962 assertNotNull(nr);
2963
Chalard Jean751bb3f2019-06-19 23:29:58 +09002964 assertThrows(BadParcelableException.class, () -> {
Etan Cohena7434272017-04-03 12:17:51 -07002965 Parcel parcelW = Parcel.obtain();
2966 nr.writeToParcel(parcelW, 0);
2967 byte[] bytes = parcelW.marshall();
2968 parcelW.recycle();
2969
2970 Parcel parcelR = Parcel.obtain();
2971 parcelR.unmarshall(bytes, 0, bytes.length);
2972 parcelR.setDataPosition(0);
2973 NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
Chalard Jean751bb3f2019-06-19 23:29:58 +09002974 });
Etan Cohenddb9ef02015-11-18 10:56:15 -08002975 }
2976
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002977 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09002978 public void testNetworkSpecifierUidSpoofSecurityException() throws Exception {
Etan Cohen859748f2017-04-03 17:42:34 -07002979 class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
2980 @Override
2981 public boolean satisfiedBy(NetworkSpecifier other) {
2982 return true;
2983 }
2984
2985 @Override
2986 public void assertValidFromUid(int requestorUid) {
2987 throw new SecurityException("failure");
2988 }
2989
2990 @Override
2991 public int describeContents() { return 0; }
2992 @Override
2993 public void writeToParcel(Parcel dest, int flags) {}
2994 }
2995
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09002996 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohen859748f2017-04-03 17:42:34 -07002997 mWiFiNetworkAgent.connect(false);
2998
2999 UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
3000 NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
3001 networkSpecifier).build();
3002 TestNetworkCallback networkCallback = new TestNetworkCallback();
Chalard Jean751bb3f2019-06-19 23:29:58 +09003003 assertThrows(SecurityException.class, () -> {
Etan Cohen859748f2017-04-03 17:42:34 -07003004 mCm.requestNetwork(networkRequest, networkCallback);
Chalard Jean751bb3f2019-06-19 23:29:58 +09003005 });
Etan Cohen859748f2017-04-03 17:42:34 -07003006 }
3007
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003008 @Test
paulhu3d67f532019-03-22 16:35:06 +08003009 public void testInvalidSignalStrength() {
3010 NetworkRequest r = new NetworkRequest.Builder()
3011 .addCapability(NET_CAPABILITY_INTERNET)
3012 .addTransportType(TRANSPORT_WIFI)
3013 .setSignalStrength(-75)
3014 .build();
3015 // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
3016 // permission should get SecurityException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003017 assertThrows(SecurityException.class, () ->
3018 mCm.registerNetworkCallback(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003019
Chalard Jean751bb3f2019-06-19 23:29:58 +09003020 assertThrows(SecurityException.class, () ->
3021 mCm.registerNetworkCallback(r, PendingIntent.getService(
3022 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003023
3024 // Requesting a Network with signal strength should get IllegalArgumentException.
Chalard Jean751bb3f2019-06-19 23:29:58 +09003025 assertThrows(IllegalArgumentException.class, () ->
3026 mCm.requestNetwork(r, new NetworkCallback()));
paulhu3d67f532019-03-22 16:35:06 +08003027
Chalard Jean751bb3f2019-06-19 23:29:58 +09003028 assertThrows(IllegalArgumentException.class, () ->
3029 mCm.requestNetwork(r, PendingIntent.getService(
3030 mServiceContext, 0, new Intent(), 0)));
paulhu3d67f532019-03-22 16:35:06 +08003031 }
3032
3033 @Test
Erik Klinea2d29402016-03-16 15:31:39 +09003034 public void testRegisterDefaultNetworkCallback() throws Exception {
3035 final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
3036 mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
3037 defaultNetworkCallback.assertNoCallback();
3038
3039 // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
3040 // whenever Wi-Fi is up. Without this, the mobile network agent is
3041 // reaped before any other activity can take place.
3042 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3043 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3044 .addTransportType(TRANSPORT_CELLULAR).build();
3045 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3046 cellNetworkCallback.assertNoCallback();
3047
3048 // Bring up cell and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003049 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003050 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003051 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3052 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003053 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003054
3055 // Bring up wifi and expect CALLBACK_AVAILABLE.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003056 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Klinea2d29402016-03-16 15:31:39 +09003057 mWiFiNetworkAgent.connect(true);
3058 cellNetworkCallback.assertNoCallback();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003059 defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003060 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003061
3062 // Bring down cell. Expect no default network callback, since it wasn't the default.
3063 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003064 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003065 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003066 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003067
3068 // Bring up cell. Expect no default network callback, since it won't be the default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003069 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinea2d29402016-03-16 15:31:39 +09003070 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003071 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003072 defaultNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003073 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003074
3075 // Bring down wifi. Expect the default network callback to notified of LOST wifi
3076 // followed by AVAILABLE cell.
3077 mWiFiNetworkAgent.disconnect();
3078 cellNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09003079 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003080 defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Klinea2d29402016-03-16 15:31:39 +09003081 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003082 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
3083 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003084 waitForIdle();
3085 assertEquals(null, mCm.getActiveNetwork());
3086
3087 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003088 final TestNetworkAgentWrapper
3089 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003090 final ArraySet<UidRange> ranges = new ArraySet<>();
3091 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003092 mMockVpn.setNetworkAgent(vpnNetworkAgent);
3093 mMockVpn.setUids(ranges);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003094 vpnNetworkAgent.connect(true);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09003095 mMockVpn.connect();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003096 defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
3097 assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
3098
3099 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003100 defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09003101 waitForIdle();
3102 assertEquals(null, mCm.getActiveNetwork());
Erik Klinea2d29402016-03-16 15:31:39 +09003103 }
3104
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003105 @Test
Erik Kline1d3db322017-02-28 16:20:20 +09003106 public void testAdditionalStateCallbacks() throws Exception {
Erik Klineacdd6392016-07-07 16:50:58 +09003107 // File a network request for mobile.
Erik Kline1d3db322017-02-28 16:20:20 +09003108 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003109 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3110 .addTransportType(TRANSPORT_CELLULAR).build();
3111 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3112
3113 // Bring up the mobile network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003114 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klineacdd6392016-07-07 16:50:58 +09003115 mCellNetworkAgent.connect(true);
3116
Erik Kline1d3db322017-02-28 16:20:20 +09003117 // We should get onAvailable(), onCapabilitiesChanged(), and
3118 // onLinkPropertiesChanged() in rapid succession. Additionally, we
3119 // should get onCapabilitiesChanged() when the mobile network validates.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003120 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003121 cellNetworkCallback.assertNoCallback();
3122
3123 // Update LinkProperties.
3124 final LinkProperties lp = new LinkProperties();
3125 lp.setInterfaceName("foonet_data0");
3126 mCellNetworkAgent.sendLinkProperties(lp);
3127 // We should get onLinkPropertiesChanged().
Chalard Jean059c4262019-09-30 17:51:12 +09003128 cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Chalard Jean6f4216f2019-06-05 01:40:32 +09003129 mCellNetworkAgent);
Erik Klineacdd6392016-07-07 16:50:58 +09003130 cellNetworkCallback.assertNoCallback();
3131
Erik Kline1d3db322017-02-28 16:20:20 +09003132 // Suspend the network.
3133 mCellNetworkAgent.suspend();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003134 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
3135 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003136 cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003137 cellNetworkCallback.assertNoCallback();
3138
Erik Klineacdd6392016-07-07 16:50:58 +09003139 // Register a garden variety default network request.
Chalard Jean804b8fb2018-01-30 22:41:41 +09003140 TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003141 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
Erik Kline1d3db322017-02-28 16:20:20 +09003142 // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
3143 // as well as onNetworkSuspended() in rapid succession.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003144 dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
Erik Klineacdd6392016-07-07 16:50:58 +09003145 dfltNetworkCallback.assertNoCallback();
Chalard Jean804b8fb2018-01-30 22:41:41 +09003146 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3147
3148 mCellNetworkAgent.resume();
3149 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
3150 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003151 cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent);
Chalard Jean804b8fb2018-01-30 22:41:41 +09003152 cellNetworkCallback.assertNoCallback();
3153
3154 dfltNetworkCallback = new TestNetworkCallback();
3155 mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
3156 // This time onNetworkSuspended should not be called.
3157 dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3158 dfltNetworkCallback.assertNoCallback();
Erik Klineacdd6392016-07-07 16:50:58 +09003159
Erik Klineacdd6392016-07-07 16:50:58 +09003160 mCm.unregisterNetworkCallback(dfltNetworkCallback);
3161 mCm.unregisterNetworkCallback(cellNetworkCallback);
3162 }
3163
Calvin On1f64f3f2016-10-11 15:10:46 -07003164 private void setCaptivePortalMode(int mode) {
3165 ContentResolver cr = mServiceContext.getContentResolver();
3166 Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
3167 }
3168
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003169 private void setAlwaysOnNetworks(boolean enable) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003170 ContentResolver cr = mServiceContext.getContentResolver();
3171 Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003172 mService.updateAlwaysOnNetworks();
Hugo Benichibb91c572017-05-22 10:44:02 +09003173 waitForIdle();
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003174 }
3175
Erik Kline79c6d052018-03-21 07:18:33 -07003176 private void setPrivateDnsSettings(String mode, String specifier) {
3177 final ContentResolver cr = mServiceContext.getContentResolver();
3178 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
3179 Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
3180 mService.updatePrivateDnsSettings();
3181 waitForIdle();
3182 }
3183
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003184 private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003185 NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
3186 assertNotNull(nc);
3187 return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
3188 }
3189
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003190 @Test
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003191 public void testBackgroundNetworks() throws Exception {
3192 // Create a background request. We can't do this ourselves because ConnectivityService
3193 // doesn't have an API for it. So just turn on mobile data always on.
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003194 setAlwaysOnNetworks(true);
paulhu86e23eb2019-11-05 18:05:05 +08003195 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003196 final NetworkRequest request = new NetworkRequest.Builder().build();
3197 final NetworkRequest fgRequest = new NetworkRequest.Builder()
3198 .addCapability(NET_CAPABILITY_FOREGROUND).build();
3199 final TestNetworkCallback callback = new TestNetworkCallback();
3200 final TestNetworkCallback fgCallback = new TestNetworkCallback();
3201 mCm.registerNetworkCallback(request, callback);
3202 mCm.registerNetworkCallback(fgRequest, fgCallback);
3203
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003204 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003205 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003206 callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3207 fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003208 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3209
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003210 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003211 mWiFiNetworkAgent.connect(true);
3212
3213 // When wifi connects, cell lingers.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003214 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003215 callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003216 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003217 fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003218 fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003219 fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003220 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3221 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3222
3223 // When lingering is complete, cell is still there but is now in the background.
Hugo Benichibb91c572017-05-22 10:44:02 +09003224 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003225 int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
Chalard Jean059c4262019-09-30 17:51:12 +09003226 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs);
Erik Kline1d3db322017-02-28 16:20:20 +09003227 // Expect a network capabilities update sans FOREGROUND.
3228 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003229 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3230 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3231
3232 // File a cell request and check that cell comes into the foreground.
3233 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3234 .addTransportType(TRANSPORT_CELLULAR).build();
3235 final TestNetworkCallback cellCallback = new TestNetworkCallback();
3236 mCm.requestNetwork(cellRequest, cellCallback);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003237 cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
3238 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003239 // Expect a network capabilities update with FOREGROUND, because the most recent
3240 // request causes its state to change.
Chalard Jean28e6b262019-11-19 21:30:44 +09003241 cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003242 callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003243 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3244 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3245
3246 // Release the request. The network immediately goes into the background, since it was not
3247 // lingering.
3248 mCm.unregisterNetworkCallback(cellCallback);
Chalard Jean059c4262019-09-30 17:51:12 +09003249 fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Erik Kline1d3db322017-02-28 16:20:20 +09003250 // Expect a network capabilities update sans FOREGROUND.
3251 callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003252 assertFalse(isForegroundNetwork(mCellNetworkAgent));
3253 assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
3254
3255 // Disconnect wifi and check that cell is foreground again.
3256 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003257 callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
3258 fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003259 fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colittie14d49a2016-07-20 21:35:19 +09003260 assertTrue(isForegroundNetwork(mCellNetworkAgent));
3261
3262 mCm.unregisterNetworkCallback(callback);
3263 mCm.unregisterNetworkCallback(fgCallback);
3264 }
3265
Hugo Benichi849b81b2017-05-25 13:42:31 +09003266 @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003267 public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003268 // TODO: turn this unit test into a real benchmarking test.
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003269 // Benchmarks connecting and switching performance in the presence of a large number of
3270 // NetworkRequests.
3271 // 1. File NUM_REQUESTS requests.
3272 // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
3273 // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
3274 // and NUM_REQUESTS onAvailable callbacks to fire.
3275 // See how long it took.
3276 final int NUM_REQUESTS = 90;
Hugo Benichi02f8f9c2017-05-29 13:13:52 +09003277 final int REGISTER_TIME_LIMIT_MS = 200;
3278 final int CONNECT_TIME_LIMIT_MS = 60;
3279 final int SWITCH_TIME_LIMIT_MS = 60;
Hugo Benichibb91c572017-05-22 10:44:02 +09003280 final int UNREGISTER_TIME_LIMIT_MS = 20;
3281
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003282 final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
3283 final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
3284 final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
3285 final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
3286
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003287 for (int i = 0; i < NUM_REQUESTS; i++) {
3288 callbacks[i] = new NetworkCallback() {
3289 @Override public void onAvailable(Network n) { availableLatch.countDown(); }
3290 @Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
3291 };
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003292 }
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003293
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003294 assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003295 for (NetworkCallback cb : callbacks) {
3296 mCm.registerNetworkCallback(request, cb);
3297 }
3298 });
3299
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003300 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003301 // Don't request that the network validate, because otherwise connect() will block until
3302 // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
3303 // and we won't actually measure anything.
3304 mCellNetworkAgent.connect(false);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003305
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003306 long onAvailableDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003307 await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003308 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003309 Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms",
3310 NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
3311 onAvailableDispatchingDuration));
3312 assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms",
3313 NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS),
3314 onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003315
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003316 // Give wifi a high enough score that we'll linger cell when wifi comes up.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003317 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003318 mWiFiNetworkAgent.adjustScore(40);
3319 mWiFiNetworkAgent.connect(false);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003320
3321 long onLostDispatchingDuration = durationOf(() -> {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003322 await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS);
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003323 });
Hugo Benichibb91c572017-05-22 10:44:02 +09003324 Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms",
3325 NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration));
3326 assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms",
3327 NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS),
3328 onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS);
Lorenzo Colitti6ee0a922016-06-27 16:44:07 +09003329
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003330 assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> {
Hugo Benichicbf8ff82016-11-15 11:25:52 +09003331 for (NetworkCallback cb : callbacks) {
3332 mCm.unregisterNetworkCallback(cb);
3333 }
3334 });
3335 }
3336
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003337 @Test
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003338 public void testMobileDataAlwaysOn() throws Exception {
paulhu86e23eb2019-11-05 18:05:05 +08003339 grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003340 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3341 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3342 .addTransportType(TRANSPORT_CELLULAR).build();
3343 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
3344
3345 final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory");
3346 handlerThread.start();
3347 NetworkCapabilities filter = new NetworkCapabilities()
3348 .addTransportType(TRANSPORT_CELLULAR)
3349 .addCapability(NET_CAPABILITY_INTERNET);
3350 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3351 mServiceContext, "testFactory", filter);
3352 testFactory.setScoreFilter(40);
3353
3354 // Register the factory and expect it to start looking for a network.
Chalard Jean05ab6812018-05-02 21:14:54 +09003355 testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003356 testFactory.register();
3357 testFactory.waitForNetworkRequests(1);
3358 assertTrue(testFactory.getMyStartRequested());
3359
3360 // Bring up wifi. The factory stops looking for a network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003361 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean05ab6812018-05-02 21:14:54 +09003362 // Score 60 - 40 penalty for not validated yet, then 60 when it validates
3363 testFactory.expectAddRequestsWithScores(20, 60);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003364 mWiFiNetworkAgent.connect(true);
Chalard Jean05ab6812018-05-02 21:14:54 +09003365 testFactory.waitForRequests();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003366 assertFalse(testFactory.getMyStartRequested());
3367
3368 ContentResolver cr = mServiceContext.getContentResolver();
3369
3370 // Turn on mobile data always on. The factory starts looking again.
Chalard Jean05ab6812018-05-02 21:14:54 +09003371 testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003372 setAlwaysOnNetworks(true);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003373 testFactory.waitForNetworkRequests(2);
3374 assertTrue(testFactory.getMyStartRequested());
3375
3376 // Bring up cell data and check that the factory stops looking.
Hugo Benichifed512a2017-06-26 10:06:49 +09003377 assertLength(1, mCm.getAllNetworks());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003378 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jean05ab6812018-05-02 21:14:54 +09003379 testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003380 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003381 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003382 testFactory.waitForNetworkRequests(2);
3383 assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
3384
3385 // Check that cell data stays up.
Hugo Benichibb91c572017-05-22 10:44:02 +09003386 waitForIdle();
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003387 verifyActiveNetwork(TRANSPORT_WIFI);
Hugo Benichifed512a2017-06-26 10:06:49 +09003388 assertLength(2, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003389
3390 // Turn off mobile data always on and expect the request to disappear...
3391 testFactory.expectRemoveRequests(1);
Leif Hendrik Wildenfd306632018-05-02 12:05:24 -07003392 setAlwaysOnNetworks(false);
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003393 testFactory.waitForNetworkRequests(1);
3394
3395 // ... and cell data to be torn down.
Chalard Jean059c4262019-09-30 17:51:12 +09003396 cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Hugo Benichifed512a2017-06-26 10:06:49 +09003397 assertLength(1, mCm.getAllNetworks());
Lorenzo Colitti762ea7a2016-06-05 21:00:23 +09003398
3399 testFactory.unregister();
3400 mCm.unregisterNetworkCallback(cellNetworkCallback);
3401 handlerThread.quit();
3402 }
3403
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003404 @Test
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003405 public void testAvoidBadWifiSetting() throws Exception {
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003406 final ContentResolver cr = mServiceContext.getContentResolver();
3407 final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
3408
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003409 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003410 String[] values = new String[] {null, "0", "1"};
3411 for (int i = 0; i < values.length; i++) {
3412 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003413 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003414 waitForIdle();
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003415 String msg = String.format("config=false, setting=%s", values[i]);
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003416 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003417 assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003418 }
3419
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003420 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003421
3422 Settings.Global.putInt(cr, settingName, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003423 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003424 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003425 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003426 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003427
3428 Settings.Global.putInt(cr, settingName, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003429 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003430 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003431 assertTrue(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003432 assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003433
3434 Settings.Global.putString(cr, settingName, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003435 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003436 waitForIdle();
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003437 assertFalse(mService.avoidBadWifi());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003438 assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003439 }
3440
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003441 @Test
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003442 public void testAvoidBadWifi() throws Exception {
Erik Kline065ab6e2016-10-02 18:02:14 +09003443 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003444
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003445 // Pretend we're on a carrier that restricts switching away from bad wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003446 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003447
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003448 // File a request for cell to ensure it doesn't go down.
3449 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
3450 final NetworkRequest cellRequest = new NetworkRequest.Builder()
3451 .addTransportType(TRANSPORT_CELLULAR).build();
3452 mCm.requestNetwork(cellRequest, cellNetworkCallback);
3453
3454 TestNetworkCallback defaultCallback = new TestNetworkCallback();
3455 mCm.registerDefaultNetworkCallback(defaultCallback);
3456
3457 NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
3458 .addTransportType(TRANSPORT_WIFI)
3459 .addCapability(NET_CAPABILITY_VALIDATED)
3460 .build();
3461 TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
3462 mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
3463
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003464 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003465 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003466
3467 // Bring up validated cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003468 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003469 mCellNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003470 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
3471 defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003472 Network cellNetwork = mCellNetworkAgent.getNetwork();
3473
3474 // Bring up validated wifi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003475 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003476 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003477 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3478 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003479 Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
3480
3481 // Fail validation on wifi.
lucaslin783f2212019-10-22 18:27:33 +08003482 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003483 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003484 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003485 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003486
3487 // Because avoid bad wifi is off, we don't switch to cellular.
3488 defaultCallback.assertNoCallback();
3489 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3490 NET_CAPABILITY_VALIDATED));
3491 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3492 NET_CAPABILITY_VALIDATED));
3493 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3494
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003495 // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
3496 // that we switch back to cell.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003497 mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
3498 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003499 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003500 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3501
3502 // Switch back to a restrictive carrier.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003503 mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
3504 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003505 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003506 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3507
3508 // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
3509 mCm.setAvoidUnvalidated(wifiNetwork);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003510 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003511 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3512 NET_CAPABILITY_VALIDATED));
3513 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3514 NET_CAPABILITY_VALIDATED));
3515 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3516
3517 // Disconnect and reconnect wifi to clear the one-time switch above.
3518 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003519 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003520 mWiFiNetworkAgent.connect(true);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003521 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
3522 validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003523 wifiNetwork = mWiFiNetworkAgent.getNetwork();
3524
3525 // Fail validation on wifi and expect the dialog to appear.
lucaslin783f2212019-10-22 18:27:33 +08003526 mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003527 mCm.reportNetworkConnectivity(wifiNetwork, false);
Erik Kline1d3db322017-02-28 16:20:20 +09003528 defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09003529 validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003530
3531 // Simulate the user selecting "switch" and checking the don't ask again checkbox.
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003532 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003533 mPolicyTracker.reevaluate();
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003534
3535 // We now switch to cell.
Lorenzo Colitti27334542018-01-12 16:22:21 +09003536 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003537 assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
3538 NET_CAPABILITY_VALIDATED));
3539 assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
3540 NET_CAPABILITY_VALIDATED));
3541 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3542
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003543 // Simulate the user turning the cellular fallback setting off and then on.
3544 // We switch to wifi and then to cell.
3545 Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003546 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003547 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003548 assertEquals(mCm.getActiveNetwork(), wifiNetwork);
3549 Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003550 mPolicyTracker.reevaluate();
Lorenzo Colitti27334542018-01-12 16:22:21 +09003551 defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
Lorenzo Colitti165c51c2016-09-19 01:00:19 +09003552 assertEquals(mCm.getActiveNetwork(), cellNetwork);
3553
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003554 // If cell goes down, we switch to wifi.
3555 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003556 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti27334542018-01-12 16:22:21 +09003557 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Lorenzo Colitti73b209382016-09-15 22:18:09 +09003558 validatedWifiCallback.assertNoCallback();
3559
3560 mCm.unregisterNetworkCallback(cellNetworkCallback);
3561 mCm.unregisterNetworkCallback(validatedWifiCallback);
3562 mCm.unregisterNetworkCallback(defaultCallback);
3563 }
3564
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003565 @Test
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003566 public void testMeteredMultipathPreferenceSetting() throws Exception {
3567 final ContentResolver cr = mServiceContext.getContentResolver();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003568 final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
3569
3570 for (int config : Arrays.asList(0, 3, 2)) {
3571 for (String setting: Arrays.asList(null, "0", "2", "1")) {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003572 mPolicyTracker.mConfigMeteredMultipathPreference = config;
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003573 Settings.Global.putString(cr, settingName, setting);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003574 mPolicyTracker.reevaluate();
Hugo Benichibb91c572017-05-22 10:44:02 +09003575 waitForIdle();
Lorenzo Colitti2de49252017-01-24 18:08:41 +09003576
3577 final int expected = (setting != null) ? Integer.parseInt(setting) : config;
3578 String msg = String.format("config=%d, setting=%s", config, setting);
3579 assertEquals(msg, expected, mCm.getMultipathPreference(null));
3580 }
3581 }
3582 }
3583
Erik Kline3841a482015-11-25 12:49:38 +09003584 /**
3585 * Validate that a satisfied network request does not trigger onUnavailable() once the
3586 * time-out period expires.
3587 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003588 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003589 public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003590 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3591 NetworkCapabilities.TRANSPORT_WIFI).build();
3592 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003593 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003594
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003595 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003596 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003597 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003598 TEST_CALLBACK_TIMEOUT_MS);
Erik Kline3841a482015-11-25 12:49:38 +09003599
3600 // pass timeout and validate that UNAVAILABLE is not called
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003601 networkCallback.assertNoCallback();
3602 }
3603
3604 /**
3605 * Validate that a satisfied network request followed by a disconnected (lost) network does
3606 * not trigger onUnavailable() once the time-out period expires.
3607 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003608 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003609 public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003610 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3611 NetworkCapabilities.TRANSPORT_WIFI).build();
3612 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Remi NGUYEN VAN4cb80622018-07-27 15:37:13 +09003613 mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003614
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003615 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003616 mWiFiNetworkAgent.connect(false);
Mike Yuf9729752018-08-17 15:22:05 +08003617 networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
Remi NGUYEN VANa7376ac2018-07-26 18:41:36 +09003618 TEST_CALLBACK_TIMEOUT_MS);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003619 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09003620 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Etan Cohenbf3b1ba2016-10-27 15:05:50 -07003621
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003622 // Validate that UNAVAILABLE is not called
Erik Kline3841a482015-11-25 12:49:38 +09003623 networkCallback.assertNoCallback();
3624 }
3625
3626 /**
3627 * Validate that when a time-out is specified for a network request the onUnavailable()
3628 * callback is called when time-out expires. Then validate that if network request is
3629 * (somehow) satisfied - the callback isn't called later.
3630 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003631 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003632 public void testTimedoutNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003633 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3634 NetworkCapabilities.TRANSPORT_WIFI).build();
3635 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003636 final int timeoutMs = 10;
3637 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003638
3639 // pass timeout and validate that UNAVAILABLE is called
Chalard Jean059c4262019-09-30 17:51:12 +09003640 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Erik Kline3841a482015-11-25 12:49:38 +09003641
3642 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003643 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003644 mWiFiNetworkAgent.connect(false);
3645 networkCallback.assertNoCallback();
3646 }
3647
3648 /**
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003649 * Validate that when a network request is unregistered (cancelled), no posterior event can
3650 * trigger the callback.
Erik Kline3841a482015-11-25 12:49:38 +09003651 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003652 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09003653 public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
Erik Kline3841a482015-11-25 12:49:38 +09003654 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3655 NetworkCapabilities.TRANSPORT_WIFI).build();
3656 final TestNetworkCallback networkCallback = new TestNetworkCallback();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003657 final int timeoutMs = 10;
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003658
Hugo Benichidfb559a2016-12-20 14:57:49 +09003659 mCm.requestNetwork(nr, networkCallback, timeoutMs);
Erik Kline3841a482015-11-25 12:49:38 +09003660 mCm.unregisterNetworkCallback(networkCallback);
Hugo Benichi91c7ff92017-06-26 10:20:00 +09003661 // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
3662 // that this callback will not be called.
Erik Kline3841a482015-11-25 12:49:38 +09003663 networkCallback.assertNoCallback();
3664
3665 // create a network satisfying request - validate that request not triggered
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003666 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Erik Kline3841a482015-11-25 12:49:38 +09003667 mWiFiNetworkAgent.connect(false);
3668 networkCallback.assertNoCallback();
3669 }
3670
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003671 @Test
3672 public void testUnfulfillableNetworkRequest() throws Exception {
3673 runUnfulfillableNetworkRequest(false);
3674 }
3675
3676 @Test
3677 public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
3678 runUnfulfillableNetworkRequest(true);
3679 }
3680
Etan Cohenddb720a2019-01-08 12:09:18 -08003681 /**
3682 * Validate the callback flow for a factory releasing a request as unfulfillable.
3683 */
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003684 private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
Etan Cohenddb720a2019-01-08 12:09:18 -08003685 NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
3686 NetworkCapabilities.TRANSPORT_WIFI).build();
3687 final TestNetworkCallback networkCallback = new TestNetworkCallback();
3688
3689 final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
3690 handlerThread.start();
3691 NetworkCapabilities filter = new NetworkCapabilities()
3692 .addTransportType(TRANSPORT_WIFI)
3693 .addCapability(NET_CAPABILITY_INTERNET);
3694 final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
3695 mServiceContext, "testFactory", filter);
3696 testFactory.setScoreFilter(40);
3697
3698 // Register the factory and expect it to receive the default request.
Etan Cohenae574a82019-01-08 12:09:18 -08003699 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003700 testFactory.register();
3701 SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
3702
3703 assertEquals(1, requests.size()); // have 1 request at this point
3704 int origRequestId = requests.valueAt(0).requestId;
3705
3706 // Now file the test request and expect it.
Chalard Jean05ab6812018-05-02 21:14:54 +09003707 testFactory.expectAddRequestsWithScores(0);
Etan Cohenddb720a2019-01-08 12:09:18 -08003708 mCm.requestNetwork(nr, networkCallback);
3709 requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
3710
3711 int newRequestId = 0;
3712 for (int i = 0; i < requests.size(); ++i) {
3713 if (requests.valueAt(i).requestId != origRequestId) {
3714 newRequestId = requests.valueAt(i).requestId;
3715 break;
3716 }
3717 }
3718
Etan Cohen22e0fc12019-05-23 08:16:20 -07003719 testFactory.expectRemoveRequests(1);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003720 if (preUnregister) {
3721 mCm.unregisterNetworkCallback(networkCallback);
Etan Cohenddb720a2019-01-08 12:09:18 -08003722
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003723 // Simulate the factory releasing the request as unfulfillable: no-op since
3724 // the callback has already been unregistered (but a test that no exceptions are
3725 // thrown).
3726 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3727 } else {
3728 // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003729 testFactory.triggerUnfulfillable(requests.get(newRequestId));
3730
Chalard Jean059c4262019-09-30 17:51:12 +09003731 networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null);
Etan Cohen4a62d1d2019-05-21 12:06:04 -07003732 testFactory.waitForRequests();
3733
3734 // unregister network callback - a no-op (since already freed by the
3735 // on-unavailable), but should not fail or throw exceptions.
3736 mCm.unregisterNetworkCallback(networkCallback);
3737 }
Etan Cohen9b09a162019-04-16 15:07:55 -07003738
Etan Cohenddb720a2019-01-08 12:09:18 -08003739 testFactory.unregister();
3740 handlerThread.quit();
3741 }
3742
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003743 private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
3744
Chalard Jeane7b24752019-06-20 16:01:19 +09003745 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003746
3747 private class CallbackValue {
3748 public CallbackType callbackType;
3749 public int error;
3750
3751 public CallbackValue(CallbackType type) {
3752 this.callbackType = type;
3753 this.error = PacketKeepalive.SUCCESS;
3754 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3755 }
3756
3757 public CallbackValue(CallbackType type, int error) {
3758 this.callbackType = type;
3759 this.error = error;
3760 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3761 }
3762
3763 @Override
3764 public boolean equals(Object o) {
3765 return o instanceof CallbackValue &&
3766 this.callbackType == ((CallbackValue) o).callbackType &&
3767 this.error == ((CallbackValue) o).error;
3768 }
3769
3770 @Override
3771 public String toString() {
3772 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error);
3773 }
3774 }
3775
junyulai7c469172019-01-16 20:23:34 +08003776 private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003777
3778 @Override
3779 public void onStarted() {
3780 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3781 }
3782
3783 @Override
3784 public void onStopped() {
3785 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3786 }
3787
3788 @Override
3789 public void onError(int error) {
3790 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3791 }
3792
Chalard Jeane7b24752019-06-20 16:01:19 +09003793 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3794 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003795 }
3796
Chalard Jeane7b24752019-06-20 16:01:19 +09003797 public void expectStarted() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003798 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3799 }
3800
Chalard Jeane7b24752019-06-20 16:01:19 +09003801 public void expectStopped() throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003802 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3803 }
3804
Chalard Jeane7b24752019-06-20 16:01:19 +09003805 public void expectError(int error) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003806 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3807 }
3808 }
3809
junyulai48eac1d42018-12-27 17:25:29 +08003810 private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
3811
3812 public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
3813
3814 private class CallbackValue {
3815 public CallbackType callbackType;
3816 public int error;
3817
3818 CallbackValue(CallbackType type) {
3819 this.callbackType = type;
3820 this.error = SocketKeepalive.SUCCESS;
3821 assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
3822 }
3823
3824 CallbackValue(CallbackType type, int error) {
3825 this.callbackType = type;
3826 this.error = error;
3827 assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
3828 }
3829
3830 @Override
3831 public boolean equals(Object o) {
3832 return o instanceof CallbackValue
3833 && this.callbackType == ((CallbackValue) o).callbackType
3834 && this.error == ((CallbackValue) o).error;
3835 }
3836
3837 @Override
3838 public String toString() {
3839 return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
3840 error);
3841 }
3842 }
3843
3844 private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
junyulai7c469172019-01-16 20:23:34 +08003845 private final Executor mExecutor;
3846
3847 TestSocketKeepaliveCallback(@NonNull Executor executor) {
3848 mExecutor = executor;
3849 }
junyulai48eac1d42018-12-27 17:25:29 +08003850
3851 @Override
3852 public void onStarted() {
3853 mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
3854 }
3855
3856 @Override
3857 public void onStopped() {
3858 mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
3859 }
3860
3861 @Override
3862 public void onError(int error) {
3863 mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
3864 }
3865
Chalard Jeane7b24752019-06-20 16:01:19 +09003866 private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
3867 assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
3868
junyulai48eac1d42018-12-27 17:25:29 +08003869 }
3870
Chalard Jeane7b24752019-06-20 16:01:19 +09003871 public void expectStarted() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003872 expectCallback(new CallbackValue(CallbackType.ON_STARTED));
3873 }
3874
Chalard Jeane7b24752019-06-20 16:01:19 +09003875 public void expectStopped() throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003876 expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
3877 }
3878
Chalard Jeane7b24752019-06-20 16:01:19 +09003879 public void expectError(int error) throws InterruptedException {
junyulai48eac1d42018-12-27 17:25:29 +08003880 expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
3881 }
junyulai7c469172019-01-16 20:23:34 +08003882
3883 public void assertNoCallback() {
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09003884 waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
junyulai7c469172019-01-16 20:23:34 +08003885 CallbackValue cv = mCallbacks.peek();
3886 assertNull("Unexpected callback: " + cv, cv);
3887 }
junyulai48eac1d42018-12-27 17:25:29 +08003888 }
3889
Chalard Jeane7b24752019-06-20 16:01:19 +09003890 private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003891 // Ensure the network is disconnected before we do anything.
3892 if (mWiFiNetworkAgent != null) {
3893 assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
3894 }
3895
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003896 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean407deb72019-11-19 16:14:30 +09003897 ConditionVariable cv = registerConnectivityBroadcast(1);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003898 mWiFiNetworkAgent.connect(true);
3899 waitFor(cv);
3900 verifyActiveNetwork(TRANSPORT_WIFI);
3901 mWiFiNetworkAgent.sendLinkProperties(lp);
Hugo Benichibb91c572017-05-22 10:44:02 +09003902 waitForIdle();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003903 return mWiFiNetworkAgent.getNetwork();
3904 }
3905
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09003906 @Test
Guang Zhub90866d2019-09-01 21:37:04 -07003907 @FlakyTest(bugId = 140305589)
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003908 public void testPacketKeepalives() throws Exception {
3909 InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
3910 InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
3911 InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
3912 InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
3913 InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
3914
Nathan Harold63dd8132018-02-14 13:09:45 -08003915 final int validKaInterval = 15;
3916 final int invalidKaInterval = 9;
3917
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003918 LinkProperties lp = new LinkProperties();
3919 lp.setInterfaceName("wlan12");
3920 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
3921 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
3922 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
3923 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
3924
3925 Network notMyNet = new Network(61234);
3926 Network myNet = connectKeepaliveNetwork(lp);
3927
3928 TestKeepaliveCallback callback = new TestKeepaliveCallback();
3929 PacketKeepalive ka;
3930
3931 // Attempt to start keepalives with invalid parameters and check for errors.
Nathan Harold63dd8132018-02-14 13:09:45 -08003932 ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003933 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3934
Nathan Harold63dd8132018-02-14 13:09:45 -08003935 ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003936 callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL);
3937
Nathan Harold63dd8132018-02-14 13:09:45 -08003938 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003939 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3940
Nathan Harold63dd8132018-02-14 13:09:45 -08003941 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003942 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3943
Nathan Harold63dd8132018-02-14 13:09:45 -08003944 // NAT-T is only supported for IPv4.
3945 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6);
3946 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003947
Nathan Harold63dd8132018-02-14 13:09:45 -08003948 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003949 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3950
Nathan Harold63dd8132018-02-14 13:09:45 -08003951 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003952 callback.expectError(PacketKeepalive.ERROR_INVALID_PORT);
3953
Nathan Harold63dd8132018-02-14 13:09:45 -08003954 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003955 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3956
Nathan Harold63dd8132018-02-14 13:09:45 -08003957 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003958 callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
3959
3960 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003961 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Nathan Harold63dd8132018-02-14 13:09:45 -08003962 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003963 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003964 mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003965 ka.stop();
3966 callback.expectStopped();
3967
3968 // Check that deleting the IP address stops the keepalive.
3969 LinkProperties bogusLp = new LinkProperties(lp);
Nathan Harold63dd8132018-02-14 13:09:45 -08003970 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003971 callback.expectStarted();
3972 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
3973 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
3974 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
3975 callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
3976 mWiFiNetworkAgent.sendLinkProperties(lp);
3977
3978 // Check that a started keepalive is stopped correctly when the network disconnects.
Nathan Harold63dd8132018-02-14 13:09:45 -08003979 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003980 callback.expectStarted();
3981 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003982 mWiFiNetworkAgent.expectDisconnected();
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003983 callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
3984
3985 // ... and that stopping it after that has no adverse effects.
Hugo Benichibb91c572017-05-22 10:44:02 +09003986 waitForIdle();
Hugo Benichidfb559a2016-12-20 14:57:49 +09003987 final Network myNetAlias = myNet;
Lorenzo Colitti30145d72017-01-27 18:46:03 +09003988 assertNull(mCm.getNetworkCapabilities(myNetAlias));
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003989 ka.stop();
3990
3991 // Reconnect.
3992 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09003993 mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003994
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003995 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
3996 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
Nathan Harold63dd8132018-02-14 13:09:45 -08003997 ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09003998 callback.expectStarted();
3999
4000 // The second one gets slot 2.
4001 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
4002 TestKeepaliveCallback callback2 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004003 PacketKeepalive ka2 = mCm.startNattKeepalive(
4004 myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004005 callback2.expectStarted();
4006
4007 // Now stop the first one and create a third. This also gets slot 1.
4008 ka.stop();
4009 callback.expectStopped();
4010
4011 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
4012 TestKeepaliveCallback callback3 = new TestKeepaliveCallback();
Nathan Harold63dd8132018-02-14 13:09:45 -08004013 PacketKeepalive ka3 = mCm.startNattKeepalive(
4014 myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4);
Lorenzo Colitti7914ce52015-09-08 13:21:48 +09004015 callback3.expectStarted();
4016
4017 ka2.stop();
4018 callback2.expectStopped();
4019
4020 ka3.stop();
4021 callback3.expectStopped();
4022 }
Udam Sainib7c24872016-01-04 12:16:14 -08004023
Xiao Maa4637112019-02-07 15:03:57 +09004024 // Helper method to prepare the executor and run test
Chalard Jeane7b24752019-06-20 16:01:19 +09004025 private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
4026 throws Exception {
junyulai06835112019-01-03 18:50:15 +08004027 final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
Xiao Maa4637112019-02-07 15:03:57 +09004028 final Executor executorInline = (Runnable r) -> r.run();
4029 functor.accept(executorSingleThread);
junyulai06835112019-01-03 18:50:15 +08004030 executorSingleThread.shutdown();
Xiao Maa4637112019-02-07 15:03:57 +09004031 functor.accept(executorInline);
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004032 }
junyulai06835112019-01-03 18:50:15 +08004033
Remi NGUYEN VANac02bc82019-02-08 17:10:50 +09004034 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004035 public void testNattSocketKeepalives() throws Exception {
4036 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
4037 runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
junyulai06835112019-01-03 18:50:15 +08004038 }
4039
4040 private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
junyulai48eac1d42018-12-27 17:25:29 +08004041 // TODO: 1. Move this outside of ConnectivityServiceTest.
junyulai06835112019-01-03 18:50:15 +08004042 // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
junyulai0c666972019-03-04 22:45:36 +08004043 // 3. Mock ipsec service.
junyulai48eac1d42018-12-27 17:25:29 +08004044 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4045 final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
4046 final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
4047 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4048 final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
4049
4050 final int validKaInterval = 15;
4051 final int invalidKaInterval = 9;
4052
4053 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004054 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4055 final int srcPort = testSocket.getPort();
junyulai48eac1d42018-12-27 17:25:29 +08004056
junyulai48eac1d42018-12-27 17:25:29 +08004057 LinkProperties lp = new LinkProperties();
4058 lp.setInterfaceName("wlan12");
4059 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4060 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4061 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4062 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4063
4064 Network notMyNet = new Network(61234);
4065 Network myNet = connectKeepaliveNetwork(lp);
4066
junyulai7c469172019-01-16 20:23:34 +08004067 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
junyulai48eac1d42018-12-27 17:25:29 +08004068
4069 // Attempt to start keepalives with invalid parameters and check for errors.
4070 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004071 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4072 notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4073 ka.start(validKaInterval);
4074 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4075 }
junyulai48eac1d42018-12-27 17:25:29 +08004076
4077 // Invalid interval.
junyulai0c666972019-03-04 22:45:36 +08004078 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4079 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4080 ka.start(invalidKaInterval);
4081 callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
4082 }
junyulai48eac1d42018-12-27 17:25:29 +08004083
4084 // Invalid destination.
junyulai0c666972019-03-04 22:45:36 +08004085 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4086 myNet, testSocket, myIPv4, dstIPv6, executor, callback)) {
4087 ka.start(validKaInterval);
4088 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4089 }
junyulai48eac1d42018-12-27 17:25:29 +08004090
4091 // Invalid source;
junyulai0c666972019-03-04 22:45:36 +08004092 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4093 myNet, testSocket, myIPv6, dstIPv4, executor, callback)) {
4094 ka.start(validKaInterval);
4095 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4096 }
junyulai48eac1d42018-12-27 17:25:29 +08004097
4098 // NAT-T is only supported for IPv4.
junyulai0c666972019-03-04 22:45:36 +08004099 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4100 myNet, testSocket, myIPv6, dstIPv6, executor, callback)) {
4101 ka.start(validKaInterval);
4102 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4103 }
junyulai48eac1d42018-12-27 17:25:29 +08004104
4105 // Sanity check before testing started keepalive.
junyulai0c666972019-03-04 22:45:36 +08004106 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4107 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4108 ka.start(validKaInterval);
4109 callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED);
4110 }
junyulai48eac1d42018-12-27 17:25:29 +08004111
4112 // Check that a started keepalive can be stopped.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004113 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004114 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4115 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4116 ka.start(validKaInterval);
4117 callback.expectStarted();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004118 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004119 ka.stop();
4120 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004121
junyulai0c666972019-03-04 22:45:36 +08004122 // Check that keepalive could be restarted.
4123 ka.start(validKaInterval);
4124 callback.expectStarted();
4125 ka.stop();
4126 callback.expectStopped();
junyulai7c469172019-01-16 20:23:34 +08004127
junyulai0c666972019-03-04 22:45:36 +08004128 // Check that keepalive can be restarted without waiting for callback.
4129 ka.start(validKaInterval);
4130 callback.expectStarted();
4131 ka.stop();
4132 ka.start(validKaInterval);
4133 callback.expectStopped();
4134 callback.expectStarted();
4135 ka.stop();
4136 callback.expectStopped();
4137 }
junyulai7c469172019-01-16 20:23:34 +08004138
junyulai48eac1d42018-12-27 17:25:29 +08004139 // Check that deleting the IP address stops the keepalive.
4140 LinkProperties bogusLp = new LinkProperties(lp);
junyulai0c666972019-03-04 22:45:36 +08004141 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4142 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4143 ka.start(validKaInterval);
4144 callback.expectStarted();
4145 bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
4146 bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
4147 mWiFiNetworkAgent.sendLinkProperties(bogusLp);
4148 callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
4149 mWiFiNetworkAgent.sendLinkProperties(lp);
4150 }
junyulai48eac1d42018-12-27 17:25:29 +08004151
4152 // Check that a started keepalive is stopped correctly when the network disconnects.
junyulai0c666972019-03-04 22:45:36 +08004153 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4154 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4155 ka.start(validKaInterval);
4156 callback.expectStarted();
4157 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004158 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004159 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
junyulai48eac1d42018-12-27 17:25:29 +08004160
junyulai0c666972019-03-04 22:45:36 +08004161 // ... and that stopping it after that has no adverse effects.
4162 waitForIdle();
4163 final Network myNetAlias = myNet;
4164 assertNull(mCm.getNetworkCapabilities(myNetAlias));
4165 ka.stop();
4166 callback.assertNoCallback();
4167 }
junyulai48eac1d42018-12-27 17:25:29 +08004168
4169 // Reconnect.
4170 myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004171 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai48eac1d42018-12-27 17:25:29 +08004172
4173 // Check that keepalive slots start from 1 and increment. The first one gets slot 1.
4174 mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
junyulai15178152019-03-27 11:00:37 +08004175 int srcPort2 = 0;
junyulai0c666972019-03-04 22:45:36 +08004176 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4177 myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
4178 ka.start(validKaInterval);
4179 callback.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004180
junyulai0c666972019-03-04 22:45:36 +08004181 // The second one gets slot 2.
4182 mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
junyulai15178152019-03-27 11:00:37 +08004183 final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
4184 srcPort2 = testSocket2.getPort();
junyulai0c666972019-03-04 22:45:36 +08004185 TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
4186 try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
4187 myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
4188 ka2.start(validKaInterval);
4189 callback2.expectStarted();
junyulai48eac1d42018-12-27 17:25:29 +08004190
junyulai0c666972019-03-04 22:45:36 +08004191 ka.stop();
4192 callback.expectStopped();
junyulai48eac1d42018-12-27 17:25:29 +08004193
junyulai0c666972019-03-04 22:45:36 +08004194 ka2.stop();
4195 callback2.expectStopped();
junyulai06835112019-01-03 18:50:15 +08004196
junyulai0c666972019-03-04 22:45:36 +08004197 testSocket.close();
4198 testSocket2.close();
4199 }
4200 }
junyulai06835112019-01-03 18:50:15 +08004201
junyulai15178152019-03-27 11:00:37 +08004202 // Check that there is no port leaked after all keepalives and sockets are closed.
junyulai05352952019-04-09 14:37:35 +08004203 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4204 // assertFalse(isUdpPortInUse(srcPort));
4205 // assertFalse(isUdpPortInUse(srcPort2));
junyulai15178152019-03-27 11:00:37 +08004206
junyulai06835112019-01-03 18:50:15 +08004207 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004208 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004209 mWiFiNetworkAgent = null;
4210 }
4211
4212 @Test
junyulaiafe9b492019-03-19 18:50:23 +08004213 public void testTcpSocketKeepalives() throws Exception {
4214 runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
Xiao Maa4637112019-02-07 15:03:57 +09004215 }
4216
4217 private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
4218 final int srcPortV4 = 12345;
4219 final int srcPortV6 = 23456;
4220 final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
4221 final InetAddress myIPv6 = InetAddress.getByName("::1");
4222
4223 final int validKaInterval = 15;
Xiao Maa4637112019-02-07 15:03:57 +09004224
4225 final LinkProperties lp = new LinkProperties();
4226 lp.setInterfaceName("wlan12");
4227 lp.addLinkAddress(new LinkAddress(myIPv6, 64));
4228 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4229 lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
4230 lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
4231
4232 final Network notMyNet = new Network(61234);
4233 final Network myNet = connectKeepaliveNetwork(lp);
4234
4235 final Socket testSocketV4 = new Socket();
4236 final Socket testSocketV6 = new Socket();
4237
junyulai7c469172019-01-16 20:23:34 +08004238 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
Xiao Maa4637112019-02-07 15:03:57 +09004239
4240 // Attempt to start Tcp keepalives with invalid parameters and check for errors.
4241 // Invalid network.
junyulai0c666972019-03-04 22:45:36 +08004242 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4243 notMyNet, testSocketV4, executor, callback)) {
4244 ka.start(validKaInterval);
4245 callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
4246 }
Xiao Maa4637112019-02-07 15:03:57 +09004247
4248 // Invalid Socket (socket is not bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004249 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4250 myNet, testSocketV4, executor, callback)) {
4251 ka.start(validKaInterval);
4252 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4253 }
Xiao Maa4637112019-02-07 15:03:57 +09004254
4255 // Invalid Socket (socket is not bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004256 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4257 myNet, testSocketV6, executor, callback)) {
4258 ka.start(validKaInterval);
4259 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4260 }
Xiao Maa4637112019-02-07 15:03:57 +09004261
4262 // Bind the socket address
4263 testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
4264 testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
4265
4266 // Invalid Socket (socket is bound with IPv4 address).
junyulai0c666972019-03-04 22:45:36 +08004267 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4268 myNet, testSocketV4, executor, callback)) {
4269 ka.start(validKaInterval);
4270 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4271 }
Xiao Maa4637112019-02-07 15:03:57 +09004272
4273 // Invalid Socket (socket is bound with IPv6 address).
junyulai0c666972019-03-04 22:45:36 +08004274 try (SocketKeepalive ka = mCm.createSocketKeepalive(
4275 myNet, testSocketV6, executor, callback)) {
4276 ka.start(validKaInterval);
4277 callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
4278 }
Xiao Maa4637112019-02-07 15:03:57 +09004279
4280 testSocketV4.close();
4281 testSocketV6.close();
4282
4283 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004284 mWiFiNetworkAgent.expectDisconnected();
Xiao Maa4637112019-02-07 15:03:57 +09004285 mWiFiNetworkAgent = null;
junyulai48eac1d42018-12-27 17:25:29 +08004286 }
4287
junyulai0c666972019-03-04 22:45:36 +08004288 private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
junyulai0c666972019-03-04 22:45:36 +08004289 final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
4290 final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
4291 final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
4292 final int validKaInterval = 15;
4293
4294 // Prepare the target network.
4295 LinkProperties lp = new LinkProperties();
4296 lp.setInterfaceName("wlan12");
4297 lp.addLinkAddress(new LinkAddress(myIPv4, 25));
4298 lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
4299 Network myNet = connectKeepaliveNetwork(lp);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004300 mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS);
4301 mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS);
junyulai0c666972019-03-04 22:45:36 +08004302
4303 TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
4304
4305 // Prepare the target file descriptor, keep only one instance.
4306 final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
junyulai15178152019-03-27 11:00:37 +08004307 final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
4308 final int srcPort = testSocket.getPort();
junyulai0c666972019-03-04 22:45:36 +08004309 final ParcelFileDescriptor testPfd =
4310 ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
4311 testSocket.close();
4312 assertTrue(isUdpPortInUse(srcPort));
4313
4314 // Start keepalive and explicit make the variable goes out of scope with try-with-resources
4315 // block.
4316 try (SocketKeepalive ka = mCm.createNattKeepalive(
4317 myNet, testPfd, myIPv4, dstIPv4, executor, callback)) {
4318 ka.start(validKaInterval);
4319 callback.expectStarted();
4320 ka.stop();
4321 callback.expectStopped();
4322 }
4323
4324 // Check that the ParcelFileDescriptor is still valid after keepalive stopped,
4325 // ErrnoException with EBADF will be thrown if the socket is closed when checking local
4326 // address.
4327 assertTrue(isUdpPortInUse(srcPort));
4328 final InetSocketAddress sa =
4329 (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor());
4330 assertEquals(anyIPv4, sa.getAddress());
4331
4332 testPfd.close();
junyulai05352952019-04-09 14:37:35 +08004333 // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
4334 // assertFalse(isUdpPortInUse(srcPort));
junyulai0c666972019-03-04 22:45:36 +08004335
4336 mWiFiNetworkAgent.disconnect();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004337 mWiFiNetworkAgent.expectDisconnected();
junyulai0c666972019-03-04 22:45:36 +08004338 mWiFiNetworkAgent = null;
4339 }
4340
4341 private static boolean isUdpPortInUse(int port) {
4342 try (DatagramSocket ignored = new DatagramSocket(port)) {
4343 return false;
Chalard Jeane7b24752019-06-20 16:01:19 +09004344 } catch (IOException alreadyInUse) {
junyulai0c666972019-03-04 22:45:36 +08004345 return true;
4346 }
4347 }
4348
junyulai48eac1d42018-12-27 17:25:29 +08004349 @Test
Udam Sainib7c24872016-01-04 12:16:14 -08004350 public void testGetCaptivePortalServerUrl() throws Exception {
4351 String url = mCm.getCaptivePortalServerUrl();
4352 assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
4353 }
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004354
4355 private static class TestNetworkPinner extends NetworkPinner {
Chalard Jeane7b24752019-06-20 16:01:19 +09004356 public static boolean awaitPin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004357 synchronized(sLock) {
4358 if (sNetwork == null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004359 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004360 }
4361 return sNetwork != null;
4362 }
4363 }
4364
Chalard Jeane7b24752019-06-20 16:01:19 +09004365 public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004366 synchronized(sLock) {
4367 if (sNetwork != null) {
Chalard Jeane7b24752019-06-20 16:01:19 +09004368 sLock.wait(timeoutMs);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004369 }
4370 return sNetwork == null;
4371 }
4372 }
4373 }
4374
4375 private void assertPinnedToWifiWithCellDefault() {
4376 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4377 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4378 }
4379
4380 private void assertPinnedToWifiWithWifiDefault() {
4381 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
4382 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4383 }
4384
4385 private void assertNotPinnedToWifi() {
4386 assertNull(mCm.getBoundNetworkForProcess());
4387 assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
4388 }
4389
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004390 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004391 public void testNetworkPinner() throws Exception {
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004392 NetworkRequest wifiRequest = new NetworkRequest.Builder()
4393 .addTransportType(TRANSPORT_WIFI)
4394 .build();
4395 assertNull(mCm.getBoundNetworkForProcess());
4396
4397 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4398 assertNull(mCm.getBoundNetworkForProcess());
4399
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004400 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004401 mCellNetworkAgent.connect(true);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004402 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004403 mWiFiNetworkAgent.connect(false);
4404
4405 // When wi-fi connects, expect to be pinned.
4406 assertTrue(TestNetworkPinner.awaitPin(100));
4407 assertPinnedToWifiWithCellDefault();
4408
4409 // Disconnect and expect the pin to drop.
4410 mWiFiNetworkAgent.disconnect();
4411 assertTrue(TestNetworkPinner.awaitUnpin(100));
4412 assertNotPinnedToWifi();
4413
4414 // Reconnecting does not cause the pin to come back.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004415 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004416 mWiFiNetworkAgent.connect(false);
4417 assertFalse(TestNetworkPinner.awaitPin(100));
4418 assertNotPinnedToWifi();
4419
4420 // Pinning while connected causes the pin to take effect immediately.
4421 TestNetworkPinner.pin(mServiceContext, wifiRequest);
4422 assertTrue(TestNetworkPinner.awaitPin(100));
4423 assertPinnedToWifiWithCellDefault();
4424
4425 // Explicitly unpin and expect to use the default network again.
4426 TestNetworkPinner.unpin();
4427 assertNotPinnedToWifi();
4428
4429 // Disconnect cell and wifi.
Chalard Jean407deb72019-11-19 16:14:30 +09004430 ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004431 mCellNetworkAgent.disconnect();
4432 mWiFiNetworkAgent.disconnect();
4433 waitFor(cv);
4434
4435 // Pinning takes effect even if the pinned network is the default when the pin is set...
4436 TestNetworkPinner.pin(mServiceContext, wifiRequest);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004437 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004438 mWiFiNetworkAgent.connect(false);
4439 assertTrue(TestNetworkPinner.awaitPin(100));
4440 assertPinnedToWifiWithWifiDefault();
4441
4442 // ... and is maintained even when that network is no longer the default.
Chalard Jean407deb72019-11-19 16:14:30 +09004443 cv = registerConnectivityBroadcast(1);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004444 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colitti531a3442016-03-01 12:55:58 +09004445 mCellNetworkAgent.connect(true);
4446 waitFor(cv);
4447 assertPinnedToWifiWithCellDefault();
4448 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004449
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004450 @Test
Hugo Benichi893a7622017-09-29 09:34:08 +09004451 public void testNetworkCallbackMaximum() {
Jeff Sharkeye0c29952018-02-20 17:24:55 -07004452 // We can only have 99 callbacks, because MultipathPolicyTracker is
4453 // already one of them.
4454 final int MAX_REQUESTS = 99;
4455 final int CALLBACKS = 89;
Hugo Benichi893a7622017-09-29 09:34:08 +09004456 final int INTENTS = 10;
4457 assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
4458
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004459 NetworkRequest networkRequest = new NetworkRequest.Builder().build();
Hugo Benichi893a7622017-09-29 09:34:08 +09004460 ArrayList<Object> registered = new ArrayList<>();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004461
Hugo Benichi893a7622017-09-29 09:34:08 +09004462 int j = 0;
4463 while (j++ < CALLBACKS / 2) {
4464 NetworkCallback cb = new NetworkCallback();
4465 mCm.requestNetwork(networkRequest, cb);
4466 registered.add(cb);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004467 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004468 while (j++ < CALLBACKS) {
4469 NetworkCallback cb = new NetworkCallback();
4470 mCm.registerNetworkCallback(networkRequest, cb);
4471 registered.add(cb);
4472 }
4473 j = 0;
4474 while (j++ < INTENTS / 2) {
4475 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
4476 mCm.requestNetwork(networkRequest, pi);
4477 registered.add(pi);
4478 }
4479 while (j++ < INTENTS) {
4480 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
4481 mCm.registerNetworkCallback(networkRequest, pi);
4482 registered.add(pi);
4483 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004484
Hugo Benichi893a7622017-09-29 09:34:08 +09004485 // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
Chalard Jean751bb3f2019-06-19 23:29:58 +09004486 assertThrows(TooManyRequestsException.class, () ->
4487 mCm.requestNetwork(networkRequest, new NetworkCallback())
4488 );
4489 assertThrows(TooManyRequestsException.class, () ->
4490 mCm.registerNetworkCallback(networkRequest, new NetworkCallback())
4491 );
4492 assertThrows(TooManyRequestsException.class, () ->
4493 mCm.requestNetwork(networkRequest,
4494 PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
4495 );
4496 assertThrows(TooManyRequestsException.class, () ->
4497 mCm.registerNetworkCallback(networkRequest,
4498 PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
4499 );
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004500
Hugo Benichi893a7622017-09-29 09:34:08 +09004501 for (Object o : registered) {
4502 if (o instanceof NetworkCallback) {
4503 mCm.unregisterNetworkCallback((NetworkCallback)o);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004504 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004505 if (o instanceof PendingIntent) {
4506 mCm.unregisterNetworkCallback((PendingIntent)o);
4507 }
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004508 }
Hugo Benichi893a7622017-09-29 09:34:08 +09004509 waitForIdle();
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004510
4511 // Test that the limit is not hit when MAX_REQUESTS requests are added and removed.
4512 for (int i = 0; i < MAX_REQUESTS; i++) {
4513 NetworkCallback networkCallback = new NetworkCallback();
4514 mCm.requestNetwork(networkRequest, networkCallback);
4515 mCm.unregisterNetworkCallback(networkCallback);
4516 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004517 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004518
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004519 for (int i = 0; i < MAX_REQUESTS; i++) {
4520 NetworkCallback networkCallback = new NetworkCallback();
4521 mCm.registerNetworkCallback(networkRequest, networkCallback);
4522 mCm.unregisterNetworkCallback(networkCallback);
4523 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004524 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004525
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004526 for (int i = 0; i < MAX_REQUESTS; i++) {
4527 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004528 PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004529 mCm.requestNetwork(networkRequest, pendingIntent);
4530 mCm.unregisterNetworkCallback(pendingIntent);
4531 }
Hugo Benichi1e5039e2017-10-12 23:09:25 +09004532 waitForIdle();
Hugo Benichi893a7622017-09-29 09:34:08 +09004533
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004534 for (int i = 0; i < MAX_REQUESTS; i++) {
4535 PendingIntent pendingIntent =
Hugo Benichi893a7622017-09-29 09:34:08 +09004536 PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
Paul Jensen4e1d3fd2016-04-08 13:56:52 -04004537 mCm.registerNetworkCallback(networkRequest, pendingIntent);
4538 mCm.unregisterNetworkCallback(pendingIntent);
4539 }
4540 }
Hugo Benichifed512a2017-06-26 10:06:49 +09004541
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004542 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004543 public void testNetworkInfoOfTypeNone() throws Exception {
Chalard Jean407deb72019-11-19 16:14:30 +09004544 ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004545
4546 verifyNoNetwork();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004547 TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004548 assertNull(mCm.getActiveNetworkInfo());
4549
4550 Network[] allNetworks = mCm.getAllNetworks();
4551 assertLength(1, allNetworks);
4552 Network network = allNetworks[0];
4553 NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
4554 assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
4555
4556 final NetworkRequest request =
4557 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
4558 final TestNetworkCallback callback = new TestNetworkCallback();
4559 mCm.registerNetworkCallback(request, callback);
4560
Hugo Benichic1014502017-07-19 10:10:52 +09004561 // Bring up wifi aware network.
lucaslin783f2212019-10-22 18:27:33 +08004562 wifiAware.connect(false, false, false /* isStrictMode */);
Lorenzo Colitti27334542018-01-12 16:22:21 +09004563 callback.expectAvailableCallbacksUnvalidated(wifiAware);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004564
4565 assertNull(mCm.getActiveNetworkInfo());
4566 assertNull(mCm.getActiveNetwork());
Hugo Benichic1014502017-07-19 10:10:52 +09004567 // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start
Hugo Benichi16f0a942017-06-20 14:07:59 +09004568 // of this test. Fix it and uncomment the assert below.
4569 //assertEmpty(mCm.getAllNetworkInfo());
4570
Hugo Benichic1014502017-07-19 10:10:52 +09004571 // Disconnect wifi aware network.
4572 wifiAware.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09004573 callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost);
Hugo Benichi16f0a942017-06-20 14:07:59 +09004574 mCm.unregisterNetworkCallback(callback);
4575
4576 verifyNoNetwork();
4577 if (broadcastCV.block(10)) {
4578 fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
4579 }
4580 }
4581
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004582 @Test
Hugo Benichi16f0a942017-06-20 14:07:59 +09004583 public void testDeprecatedAndUnsupportedOperations() throws Exception {
4584 final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
4585 assertNull(mCm.getNetworkInfo(TYPE_NONE));
4586 assertNull(mCm.getNetworkForType(TYPE_NONE));
4587 assertNull(mCm.getLinkProperties(TYPE_NONE));
4588 assertFalse(mCm.isNetworkSupported(TYPE_NONE));
4589
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004590 assertThrows(IllegalArgumentException.class,
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004591 () -> mCm.networkCapabilitiesForType(TYPE_NONE));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004592
4593 Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004594 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, ""));
4595 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, ""));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004596 // TODO: let test context have configuration application target sdk version
4597 // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
Chalard Jean3da8e0f2019-09-20 17:19:31 +09004598 assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, ""));
4599 assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, ""));
4600 assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null));
Hugo Benichi16f0a942017-06-20 14:07:59 +09004601 }
4602
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09004603 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09004604 public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
Rubin Xu1bb5c082017-09-05 18:40:49 +01004605 final NetworkRequest networkRequest = new NetworkRequest.Builder()
4606 .addTransportType(TRANSPORT_WIFI).build();
4607 final TestNetworkCallback networkCallback = new TestNetworkCallback();
4608 mCm.registerNetworkCallback(networkRequest, networkCallback);
4609
4610 LinkProperties lp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004611 lp.setInterfaceName(WIFI_IFNAME);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004612 LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
4613 RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
4614 NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
4615 lp.addLinkAddress(myIpv4Address);
4616 lp.addRoute(myIpv4DefaultRoute);
4617
4618 // Verify direct routes are added when network agent is first registered in
4619 // ConnectivityService.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004620 TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004621 networkAgent.connect(true);
Chalard Jean059c4262019-09-30 17:51:12 +09004622 networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent);
4623 networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent);
4624 CallbackEntry.LinkPropertiesChanged cbi =
4625 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
Rubin Xu1bb5c082017-09-05 18:40:49 +01004626 networkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004627 networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004628 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
4629 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004630 checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004631 Arrays.asList(myIpv4DefaultRoute));
4632 checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
4633 Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
4634
4635 // Verify direct routes are added during subsequent link properties updates.
4636 LinkProperties newLp = new LinkProperties(lp);
4637 LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
4638 LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
4639 newLp.addLinkAddress(myIpv6Address1);
4640 newLp.addLinkAddress(myIpv6Address2);
4641 networkAgent.sendLinkProperties(newLp);
Chalard Jean059c4262019-09-30 17:51:12 +09004642 cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent);
Rubin Xu1bb5c082017-09-05 18:40:49 +01004643 networkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004644 checkDirectlyConnectedRoutes(cbi.getLp(),
Rubin Xu1bb5c082017-09-05 18:40:49 +01004645 Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
4646 Arrays.asList(myIpv4DefaultRoute));
4647 mCm.unregisterNetworkCallback(networkCallback);
4648 }
4649
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004650 @Test
4651 public void testStatsIfacesChanged() throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004652 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
4653 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004654
Varun Anandd33cbc62019-02-07 14:13:13 -08004655 Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
4656 Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
4657
4658 LinkProperties cellLp = new LinkProperties();
4659 cellLp.setInterfaceName(MOBILE_IFNAME);
4660 LinkProperties wifiLp = new LinkProperties();
4661 wifiLp.setInterfaceName(WIFI_IFNAME);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004662
4663 // Simple connection should have updated ifaces
4664 mCellNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004665 mCellNetworkAgent.sendLinkProperties(cellLp);
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004666 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004667 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004668 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4669 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004670 reset(mStatsService);
4671
4672 // Default network switch should update ifaces.
4673 mWiFiNetworkAgent.connect(false);
Varun Anandd33cbc62019-02-07 14:13:13 -08004674 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
Lorenzo Colittic78da292018-01-19 00:50:48 +09004675 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004676 assertEquals(wifiLp, mService.getActiveLinkProperties());
4677 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004678 .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
4679 eq(new VpnInfo[0]));
Lorenzo Colittic78da292018-01-19 00:50:48 +09004680 reset(mStatsService);
4681
4682 // Disconnect should update ifaces.
4683 mWiFiNetworkAgent.disconnect();
4684 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004685 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004686 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
4687 eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004688 reset(mStatsService);
4689
4690 // Metered change should update ifaces
4691 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4692 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004693 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004694 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4695 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004696 reset(mStatsService);
4697
4698 mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4699 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004700 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004701 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4702 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004703 reset(mStatsService);
4704
4705 // Captive portal change shouldn't update ifaces
4706 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
4707 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004708 verify(mStatsService, never())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004709 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4710 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004711 reset(mStatsService);
4712
4713 // Roaming change should update ifaces
4714 mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
4715 waitForIdle();
Varun Anandd33cbc62019-02-07 14:13:13 -08004716 verify(mStatsService, atLeastOnce())
Lorenzo Colitti4aa87602019-06-24 13:50:45 +09004717 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
4718 eq(new VpnInfo[0]));
Jeff Sharkey72f9c422017-10-27 17:22:59 -06004719 reset(mStatsService);
4720 }
4721
Erik Klinee89953b2018-01-11 16:11:10 +09004722 @Test
4723 public void testBasicDnsConfigurationPushed() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004724 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Erik Kline79c6d052018-03-21 07:18:33 -07004725
4726 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004727 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004728
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004729 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Klinee89953b2018-01-11 16:11:10 +09004730 waitForIdle();
waynema13516842019-03-12 18:13:49 +08004731 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004732 verifyNoMoreInteractions(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004733
4734 final LinkProperties cellLp = new LinkProperties();
Erik Kline79c6d052018-03-21 07:18:33 -07004735 cellLp.setInterfaceName(MOBILE_IFNAME);
Erik Kline117e7f32018-03-04 21:01:01 +09004736 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4737 // "is-reachable" testing in order to not program netd with unreachable
4738 // nameservers that it might try repeated to validate.
4739 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
Erik Kline79c6d052018-03-21 07:18:33 -07004740 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4741 MOBILE_IFNAME));
Erik Kline117e7f32018-03-04 21:01:01 +09004742 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
Erik Kline79c6d052018-03-21 07:18:33 -07004743 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4744 MOBILE_IFNAME));
Erik Klinee89953b2018-01-11 16:11:10 +09004745 mCellNetworkAgent.sendLinkProperties(cellLp);
4746 mCellNetworkAgent.connect(false);
4747 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004748
4749 verify(mMockDnsResolver, times(1)).createNetworkCache(
4750 eq(mCellNetworkAgent.getNetwork().netId));
4751 // CS tells dnsresolver about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004752 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004753 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004754
4755 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4756 mCellNetworkAgent.sendLinkProperties(cellLp);
4757 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004758 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004759 mResolverParamsParcelCaptor.capture());
4760 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4761 assertEquals(1, resolvrParams.servers.length);
4762 assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
Erik Kline79c6d052018-03-21 07:18:33 -07004763 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004764 assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
Luke Huang65914772019-03-16 00:31:46 +08004765 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004766
4767 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4768 mCellNetworkAgent.sendLinkProperties(cellLp);
4769 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004770 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004771 mResolverParamsParcelCaptor.capture());
4772 resolvrParams = mResolverParamsParcelCaptor.getValue();
4773 assertEquals(2, resolvrParams.servers.length);
4774 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Kline117e7f32018-03-04 21:01:01 +09004775 new String[]{"2001:db8::1", "192.0.2.1"}));
Erik Kline79c6d052018-03-21 07:18:33 -07004776 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004777 assertEquals(2, resolvrParams.tlsServers.length);
4778 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Erik Kline79c6d052018-03-21 07:18:33 -07004779 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004780 reset(mMockDnsResolver);
Erik Kline117e7f32018-03-04 21:01:01 +09004781
4782 final String TLS_SPECIFIER = "tls.example.com";
4783 final String TLS_SERVER6 = "2001:db8:53::53";
4784 final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
4785 final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09004786 mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
4787 new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
4788
Erik Kline117e7f32018-03-04 21:01:01 +09004789 waitForIdle();
Luke Huang65914772019-03-16 00:31:46 +08004790 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004791 mResolverParamsParcelCaptor.capture());
4792 resolvrParams = mResolverParamsParcelCaptor.getValue();
4793 assertEquals(2, resolvrParams.servers.length);
4794 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Erik Klinee89953b2018-01-11 16:11:10 +09004795 new String[]{"2001:db8::1", "192.0.2.1"}));
Luke Huang65914772019-03-16 00:31:46 +08004796 reset(mMockDnsResolver);
Erik Klinee89953b2018-01-11 16:11:10 +09004797 }
4798
Erik Kline79c6d052018-03-21 07:18:33 -07004799 @Test
lucaslin783f2212019-10-22 18:27:33 +08004800 public void testPrivateDnsNotification() throws Exception {
4801 NetworkRequest request = new NetworkRequest.Builder()
4802 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
4803 .build();
4804 TestNetworkCallback callback = new TestNetworkCallback();
4805 mCm.registerNetworkCallback(request, callback);
4806 // Bring up wifi.
4807 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
4808 mWiFiNetworkAgent.connect(false);
4809 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
4810 // Private DNS resolution failed, checking if the notification will be shown or not.
4811 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4812 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4813 waitForIdle();
4814 // If network validation failed, NetworkMonitor will re-evaluate the network.
4815 // ConnectivityService should filter the redundant notification. This part is trying to
4816 // simulate that situation and check if ConnectivityService could filter that case.
4817 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4818 waitForIdle();
4819 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
4820 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4821 // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
4822 // shown.
4823 mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
4824 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4825 waitForIdle();
4826 verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
4827 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
4828 // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
4829 // shown again.
4830 mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
4831 mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
4832 waitForIdle();
4833 verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
4834 eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
4835 }
4836
4837 @Test
Erik Kline79c6d052018-03-21 07:18:33 -07004838 public void testPrivateDnsSettingsChange() throws Exception {
Erik Kline79c6d052018-03-21 07:18:33 -07004839 // Clear any interactions that occur as a result of CS starting up.
Luke Huang65914772019-03-16 00:31:46 +08004840 reset(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004841
4842 // The default on Android is opportunistic mode ("Automatic").
4843 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4844
dalyk1fcb7392018-03-05 12:42:22 -05004845 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4846 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4847 .addTransportType(TRANSPORT_CELLULAR).build();
4848 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4849
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004850 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Erik Kline79c6d052018-03-21 07:18:33 -07004851 waitForIdle();
4852 // CS tells netd about the empty DNS config for this network.
waynema13516842019-03-12 18:13:49 +08004853 verify(mMockDnsResolver, never()).setResolverConfiguration(any());
Luke Huang65914772019-03-16 00:31:46 +08004854 verifyNoMoreInteractions(mMockDnsResolver);
Erik Kline79c6d052018-03-21 07:18:33 -07004855
4856 final LinkProperties cellLp = new LinkProperties();
4857 cellLp.setInterfaceName(MOBILE_IFNAME);
4858 // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
4859 // "is-reachable" testing in order to not program netd with unreachable
4860 // nameservers that it might try repeated to validate.
4861 cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
4862 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
4863 MOBILE_IFNAME));
4864 cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
4865 cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
4866 MOBILE_IFNAME));
4867 cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
4868 cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
4869
4870 mCellNetworkAgent.sendLinkProperties(cellLp);
4871 mCellNetworkAgent.connect(false);
4872 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08004873 verify(mMockDnsResolver, times(1)).createNetworkCache(
4874 eq(mCellNetworkAgent.getNetwork().netId));
Luke Huang65914772019-03-16 00:31:46 +08004875 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004876 mResolverParamsParcelCaptor.capture());
4877 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
4878 assertEquals(2, resolvrParams.tlsServers.length);
4879 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004880 new String[] { "2001:db8::1", "192.0.2.1" }));
Erik Kline79c6d052018-03-21 07:18:33 -07004881 // Opportunistic mode.
waynema13516842019-03-12 18:13:49 +08004882 assertEquals(2, resolvrParams.tlsServers.length);
4883 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004884 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004885 reset(mMockDnsResolver);
Chalard Jean059c4262019-09-30 17:51:12 +09004886 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
4887 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004888 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004889 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4890 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4891 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004892 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004893 assertFalse(cbi.getLp().isPrivateDnsActive());
4894 assertNull(cbi.getLp().getPrivateDnsServerName());
Erik Kline79c6d052018-03-21 07:18:33 -07004895
4896 setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004897 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004898 mResolverParamsParcelCaptor.capture());
4899 resolvrParams = mResolverParamsParcelCaptor.getValue();
4900 assertEquals(2, resolvrParams.servers.length);
4901 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004902 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004903 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004904 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004905
4906 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
Luke Huang65914772019-03-16 00:31:46 +08004907 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08004908 mResolverParamsParcelCaptor.capture());
4909 resolvrParams = mResolverParamsParcelCaptor.getValue();
4910 assertEquals(2, resolvrParams.servers.length);
4911 assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004912 new String[] { "2001:db8::1", "192.0.2.1" }));
waynema13516842019-03-12 18:13:49 +08004913 assertEquals(2, resolvrParams.tlsServers.length);
4914 assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
Chalard Jean9c0ff1b2019-05-30 17:11:14 +09004915 new String[] { "2001:db8::1", "192.0.2.1" }));
Luke Huang65914772019-03-16 00:31:46 +08004916 reset(mMockDnsResolver);
dalyk1fcb7392018-03-05 12:42:22 -05004917 cellNetworkCallback.assertNoCallback();
Erik Kline79c6d052018-03-21 07:18:33 -07004918
dalyk1fcb7392018-03-05 12:42:22 -05004919 setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
4920 // Can't test dns configuration for strict mode without properly mocking
4921 // out the DNS lookups, but can test that LinkProperties is updated.
Chalard Jean059c4262019-09-30 17:51:12 +09004922 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004923 mCellNetworkAgent);
4924 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004925 assertTrue(cbi.getLp().isPrivateDnsActive());
4926 assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004927 }
4928
4929 @Test
4930 public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception {
4931 // The default on Android is opportunistic mode ("Automatic").
4932 setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
4933
4934 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
4935 final NetworkRequest cellRequest = new NetworkRequest.Builder()
4936 .addTransportType(TRANSPORT_CELLULAR).build();
4937 mCm.requestNetwork(cellRequest, cellNetworkCallback);
4938
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09004939 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
dalyk1fcb7392018-03-05 12:42:22 -05004940 waitForIdle();
4941 LinkProperties lp = new LinkProperties();
4942 mCellNetworkAgent.sendLinkProperties(lp);
4943 mCellNetworkAgent.connect(false);
4944 waitForIdle();
Chalard Jean059c4262019-09-30 17:51:12 +09004945 cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
4946 cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED,
dalyk1fcb7392018-03-05 12:42:22 -05004947 mCellNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09004948 CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
4949 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
4950 cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent);
dalyk1fcb7392018-03-05 12:42:22 -05004951 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004952 assertFalse(cbi.getLp().isPrivateDnsActive());
4953 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004954 Set<InetAddress> dnsServers = new HashSet<>();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004955 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004956
4957 // Send a validation event for a server that is not part of the current
4958 // resolver config. The validation event should be ignored.
4959 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4960 mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true);
4961 cellNetworkCallback.assertNoCallback();
4962
4963 // Add a dns server to the LinkProperties.
4964 LinkProperties lp2 = new LinkProperties(lp);
4965 lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
4966 mCellNetworkAgent.sendLinkProperties(lp2);
Chalard Jean059c4262019-09-30 17:51:12 +09004967 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004968 mCellNetworkAgent);
4969 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004970 assertFalse(cbi.getLp().isPrivateDnsActive());
4971 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05004972 dnsServers.add(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09004973 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004974
4975 // Send a validation event containing a hostname that is not part of
4976 // the current resolver config. The validation event should be ignored.
4977 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4978 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true);
4979 cellNetworkCallback.assertNoCallback();
4980
4981 // Send a validation event where validation failed.
4982 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4983 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false);
4984 cellNetworkCallback.assertNoCallback();
4985
4986 // Send a validation event where validation succeeded for a server in
4987 // the current resolver config. A LinkProperties callback with updated
4988 // private dns fields should be sent.
4989 mService.mNetdEventCallback.onPrivateDnsValidationEvent(
4990 mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
Chalard Jean059c4262019-09-30 17:51:12 +09004991 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05004992 mCellNetworkAgent);
4993 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09004994 assertTrue(cbi.getLp().isPrivateDnsActive());
4995 assertNull(cbi.getLp().getPrivateDnsServerName());
4996 checkDnsServers(cbi.getLp(), dnsServers);
dalyk1fcb7392018-03-05 12:42:22 -05004997
4998 // The private dns fields in LinkProperties should be preserved when
4999 // the network agent sends unrelated changes.
5000 LinkProperties lp3 = new LinkProperties(lp2);
5001 lp3.setMtu(1300);
5002 mCellNetworkAgent.sendLinkProperties(lp3);
Chalard Jean059c4262019-09-30 17:51:12 +09005003 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005004 mCellNetworkAgent);
5005 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005006 assertTrue(cbi.getLp().isPrivateDnsActive());
5007 assertNull(cbi.getLp().getPrivateDnsServerName());
5008 checkDnsServers(cbi.getLp(), dnsServers);
5009 assertEquals(1300, cbi.getLp().getMtu());
dalyk1fcb7392018-03-05 12:42:22 -05005010
5011 // Removing the only validated server should affect the private dns
5012 // fields in LinkProperties.
5013 LinkProperties lp4 = new LinkProperties(lp3);
5014 lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
5015 mCellNetworkAgent.sendLinkProperties(lp4);
Chalard Jean059c4262019-09-30 17:51:12 +09005016 cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
dalyk1fcb7392018-03-05 12:42:22 -05005017 mCellNetworkAgent);
5018 cellNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005019 assertFalse(cbi.getLp().isPrivateDnsActive());
5020 assertNull(cbi.getLp().getPrivateDnsServerName());
dalyk1fcb7392018-03-05 12:42:22 -05005021 dnsServers.remove(InetAddress.getByName("145.100.185.16"));
Chalard Jean6f4216f2019-06-05 01:40:32 +09005022 checkDnsServers(cbi.getLp(), dnsServers);
5023 assertEquals(1300, cbi.getLp().getMtu());
Erik Kline79c6d052018-03-21 07:18:33 -07005024 }
5025
Rubin Xu1bb5c082017-09-05 18:40:49 +01005026 private void checkDirectlyConnectedRoutes(Object callbackObj,
5027 Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
5028 assertTrue(callbackObj instanceof LinkProperties);
5029 LinkProperties lp = (LinkProperties) callbackObj;
5030
5031 Set<RouteInfo> expectedRoutes = new ArraySet<>();
5032 expectedRoutes.addAll(otherRoutes);
5033 for (LinkAddress address : linkAddresses) {
5034 RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
5035 // Duplicates in linkAddresses are considered failures
5036 assertTrue(expectedRoutes.add(localRoute));
5037 }
5038 List<RouteInfo> observedRoutes = lp.getRoutes();
5039 assertEquals(expectedRoutes.size(), observedRoutes.size());
5040 assertTrue(observedRoutes.containsAll(expectedRoutes));
5041 }
5042
dalyk1fcb7392018-03-05 12:42:22 -05005043 private static void checkDnsServers(Object callbackObj, Set<InetAddress> dnsServers) {
5044 assertTrue(callbackObj instanceof LinkProperties);
5045 LinkProperties lp = (LinkProperties) callbackObj;
5046 assertEquals(dnsServers.size(), lp.getDnsServers().size());
5047 assertTrue(lp.getDnsServers().containsAll(dnsServers));
5048 }
5049
Chalard Jean0b214af2018-01-12 17:22:49 +09005050 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005051 public void testVpnNetworkActive() throws Exception {
Chalard Jean0b214af2018-01-12 17:22:49 +09005052 final int uid = Process.myUid();
5053
5054 final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005055 final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005056 final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
5057 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005058 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
Chalard Jeanb552c462018-02-21 18:43:54 +09005059 final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
5060 final NetworkRequest genericRequest = new NetworkRequest.Builder()
5061 .removeCapability(NET_CAPABILITY_NOT_VPN).build();
Chalard Jean0b214af2018-01-12 17:22:49 +09005062 final NetworkRequest wifiRequest = new NetworkRequest.Builder()
5063 .addTransportType(TRANSPORT_WIFI).build();
5064 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
Chalard Jeanb552c462018-02-21 18:43:54 +09005065 .removeCapability(NET_CAPABILITY_NOT_VPN)
Chalard Jean0b214af2018-01-12 17:22:49 +09005066 .addTransportType(TRANSPORT_VPN).build();
5067 mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
Chalard Jeanb552c462018-02-21 18:43:54 +09005068 mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005069 mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
5070 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005071 mCm.registerDefaultNetworkCallback(defaultCallback);
5072 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005073
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005074 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean0b214af2018-01-12 17:22:49 +09005075 mWiFiNetworkAgent.connect(false);
5076
5077 genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005078 genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005079 wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005080 defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005081 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005082 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005083
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005084 final TestNetworkAgentWrapper
5085 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean0b214af2018-01-12 17:22:49 +09005086 final ArraySet<UidRange> ranges = new ArraySet<>();
5087 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005088 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5089 mMockVpn.setUids(ranges);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005090 // VPN networks do not satisfy the default request and are automatically validated
5091 // by NetworkMonitor
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005092 assertFalse(NetworkMonitorUtils.isValidationRequired(
5093 vpnNetworkAgent.getNetworkCapabilities()));
lucaslin783f2212019-10-22 18:27:33 +08005094 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +09005095
Chalard Jean0b214af2018-01-12 17:22:49 +09005096 vpnNetworkAgent.connect(false);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005097 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005098 mMockVpn.setUnderlyingNetworks(new Network[0]);
Chalard Jean0b214af2018-01-12 17:22:49 +09005099
5100 genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005101 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005102 wifiNetworkCallback.assertNoCallback();
5103 vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005104 defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5105 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005106
Chalard Jean059c4262019-09-30 17:51:12 +09005107 genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005108 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005109 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
Chalard Jean059c4262019-09-30 17:51:12 +09005110 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005111 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005112
5113 ranges.clear();
5114 vpnNetworkAgent.setUids(ranges);
5115
Chalard Jean059c4262019-09-30 17:51:12 +09005116 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005117 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005118 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005119 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005120
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005121 // TODO : The default network callback should actually get a LOST call here (also see the
5122 // comment below for AVAILABLE). This is because ConnectivityService does not look at UID
5123 // ranges at all when determining whether a network should be rematched. In practice, VPNs
5124 // can't currently update their UIDs without disconnecting, so this does not matter too
5125 // much, but that is the reason the test here has to check for an update to the
5126 // capabilities instead of the expected LOST then AVAILABLE.
Chalard Jean059c4262019-09-30 17:51:12 +09005127 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005128
Chalard Jean0b214af2018-01-12 17:22:49 +09005129 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005130 mMockVpn.setUids(ranges);
Varun Anand4fa80e82019-02-06 10:13:38 -08005131 vpnNetworkAgent.setUids(ranges);
Chalard Jean0b214af2018-01-12 17:22:49 +09005132
5133 genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005134 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005135 wifiNetworkCallback.assertNoCallback();
5136 vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005137 // TODO : Here like above, AVAILABLE would be correct, but because this can't actually
5138 // happen outside of the test, ConnectivityService does not rematch callbacks.
Chalard Jean059c4262019-09-30 17:51:12 +09005139 defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005140
5141 mWiFiNetworkAgent.disconnect();
5142
Chalard Jean059c4262019-09-30 17:51:12 +09005143 genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5144 genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
5145 wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chalard Jean0b214af2018-01-12 17:22:49 +09005146 vpnNetworkCallback.assertNoCallback();
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005147 defaultCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005148
5149 vpnNetworkAgent.disconnect();
5150
Chalard Jean059c4262019-09-30 17:51:12 +09005151 genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanb552c462018-02-21 18:43:54 +09005152 genericNotVpnNetworkCallback.assertNoCallback();
Chalard Jean0b214af2018-01-12 17:22:49 +09005153 wifiNetworkCallback.assertNoCallback();
Chalard Jean059c4262019-09-30 17:51:12 +09005154 vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
5155 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005156 assertEquals(null, mCm.getActiveNetwork());
Chalard Jean0b214af2018-01-12 17:22:49 +09005157
5158 mCm.unregisterNetworkCallback(genericNetworkCallback);
5159 mCm.unregisterNetworkCallback(wifiNetworkCallback);
5160 mCm.unregisterNetworkCallback(vpnNetworkCallback);
Chalard Jeanfb0c87e2018-04-18 19:18:58 +09005161 mCm.unregisterNetworkCallback(defaultCallback);
Chalard Jean0b214af2018-01-12 17:22:49 +09005162 }
Chalard Jean26400492018-04-18 20:18:38 +09005163
5164 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005165 public void testVpnWithoutInternet() throws Exception {
Chalard Jean26400492018-04-18 20:18:38 +09005166 final int uid = Process.myUid();
5167
5168 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5169 mCm.registerDefaultNetworkCallback(defaultCallback);
Chalard Jean26400492018-04-18 20:18:38 +09005170
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005171 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jean26400492018-04-18 20:18:38 +09005172 mWiFiNetworkAgent.connect(true);
5173
5174 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5175 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5176
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005177 TestNetworkAgentWrapper
5178 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jean26400492018-04-18 20:18:38 +09005179 final ArraySet<UidRange> ranges = new ArraySet<>();
5180 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005181 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5182 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005183 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5184 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005185 mMockVpn.connect();
Chalard Jean26400492018-04-18 20:18:38 +09005186
5187 defaultCallback.assertNoCallback();
5188 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5189
5190 vpnNetworkAgent.disconnect();
5191 defaultCallback.assertNoCallback();
5192
Varun Anand4fa80e82019-02-06 10:13:38 -08005193 mCm.unregisterNetworkCallback(defaultCallback);
5194 }
5195
5196 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005197 public void testVpnWithInternet() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005198 final int uid = Process.myUid();
5199
5200 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5201 mCm.registerDefaultNetworkCallback(defaultCallback);
5202
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005203 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005204 mWiFiNetworkAgent.connect(true);
5205
5206 defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
5207 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5208
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005209 TestNetworkAgentWrapper
5210 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005211 final ArraySet<UidRange> ranges = new ArraySet<>();
5212 ranges.add(new UidRange(uid, uid));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005213 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5214 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005215 vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
5216 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005217 mMockVpn.connect();
Varun Anand4fa80e82019-02-06 10:13:38 -08005218
Chalard Jean26400492018-04-18 20:18:38 +09005219 defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5220 assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
5221
5222 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005223 defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Chalard Jean26400492018-04-18 20:18:38 +09005224 defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
5225
Chalard Jean26400492018-04-18 20:18:38 +09005226 mCm.unregisterNetworkCallback(defaultCallback);
5227 }
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005228
5229 @Test
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005230 public void testVpnUnvalidated() throws Exception {
5231 final TestNetworkCallback callback = new TestNetworkCallback();
5232 mCm.registerDefaultNetworkCallback(callback);
5233
5234 // Bring up Ethernet.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005235 mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005236 mEthernetNetworkAgent.connect(true);
5237 callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
5238 callback.assertNoCallback();
5239
5240 // Bring up a VPN that has the INTERNET capability, initially unvalidated.
5241 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005242 final TestNetworkAgentWrapper
5243 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005244 final ArraySet<UidRange> ranges = new ArraySet<>();
5245 ranges.add(new UidRange(uid, uid));
5246 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5247 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005248 vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
5249 false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005250 mMockVpn.connect();
5251
5252 // Even though the VPN is unvalidated, it becomes the default network for our app.
5253 callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
5254 // TODO: this looks like a spurious callback.
Chalard Jean059c4262019-09-30 17:51:12 +09005255 callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005256 callback.assertNoCallback();
5257
5258 assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
5259 assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
5260 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5261
5262 NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5263 assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
5264 assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
5265
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005266 assertFalse(NetworkMonitorUtils.isValidationRequired(
5267 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005268 assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005269 vpnNetworkAgent.getNetworkCapabilities()));
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005270
5271 // Pretend that the VPN network validates.
lucaslin783f2212019-10-22 18:27:33 +08005272 vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005273 vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
5274 // Expect to see the validated capability, but no other changes, because the VPN is already
5275 // the default network for the app.
5276 callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
5277 callback.assertNoCallback();
5278
5279 vpnNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005280 callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
Lorenzo Colitti80986d92019-03-22 00:28:28 +09005281 callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
5282 }
5283
5284 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005285 public void testVpnSetUnderlyingNetworks() throws Exception {
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005286 final int uid = Process.myUid();
5287
5288 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5289 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5290 .removeCapability(NET_CAPABILITY_NOT_VPN)
5291 .addTransportType(TRANSPORT_VPN)
5292 .build();
5293 NetworkCapabilities nc;
5294 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5295 vpnNetworkCallback.assertNoCallback();
5296
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005297 final TestNetworkAgentWrapper
5298 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005299 final ArraySet<UidRange> ranges = new ArraySet<>();
5300 ranges.add(new UidRange(uid, uid));
5301 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5302 mMockVpn.connect();
5303 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005304 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5305 false /* isStrictMode */);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005306
5307 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5308 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5309 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5310 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5311 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5312 // For safety reasons a VPN without underlying networks is considered metered.
5313 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5314
5315 // Connect cell and use it as an underlying network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005316 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005317 mCellNetworkAgent.connect(true);
5318
5319 mService.setUnderlyingNetworksForVpn(
5320 new Network[] { mCellNetworkAgent.getNetwork() });
5321
Chalard Jean6f4216f2019-06-05 01:40:32 +09005322 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5323 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005324 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005325 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005326
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005327 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005328 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5329 mWiFiNetworkAgent.connect(true);
5330
5331 mService.setUnderlyingNetworksForVpn(
5332 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5333
Chalard Jean6f4216f2019-06-05 01:40:32 +09005334 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5335 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005336 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005337 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005338
5339 // Don't disconnect, but note the VPN is not using wifi any more.
5340 mService.setUnderlyingNetworksForVpn(
5341 new Network[] { mCellNetworkAgent.getNetwork() });
5342
Chalard Jean6f4216f2019-06-05 01:40:32 +09005343 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5344 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005345 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005346 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005347
5348 // Use Wifi but not cell. Note the VPN is now unmetered.
5349 mService.setUnderlyingNetworksForVpn(
5350 new Network[] { mWiFiNetworkAgent.getNetwork() });
5351
Chalard Jean6f4216f2019-06-05 01:40:32 +09005352 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5353 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005354 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005355 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005356
5357 // Use both again.
5358 mService.setUnderlyingNetworksForVpn(
5359 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5360
Chalard Jean6f4216f2019-06-05 01:40:32 +09005361 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5362 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005363 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005364 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005365
Chalard Jean6b65ec72018-05-18 22:02:56 +09005366 // Disconnect cell. Receive update without even removing the dead network from the
5367 // underlying networks – it's dead anyway. Not metered any more.
5368 mCellNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005369 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5370 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005371 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005372 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005373
Chalard Jeanb3ab0d12018-05-21 15:30:56 +09005374 // Disconnect wifi too. No underlying networks means this is now metered.
Chalard Jean6b65ec72018-05-18 22:02:56 +09005375 mWiFiNetworkAgent.disconnect();
Chalard Jean6f4216f2019-06-05 01:40:32 +09005376 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5377 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Chalard Jean6b65ec72018-05-18 22:02:56 +09005378 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005379 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Chalard Jeanf89e8da2018-05-18 21:47:45 +09005380
5381 mMockVpn.disconnect();
5382 }
junyulai4a192e22018-06-13 15:00:37 +08005383
Mike Yuf9729752018-08-17 15:22:05 +08005384 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005385 public void testNullUnderlyingNetworks() throws Exception {
Varun Anand4fa80e82019-02-06 10:13:38 -08005386 final int uid = Process.myUid();
5387
5388 final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
5389 final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
5390 .removeCapability(NET_CAPABILITY_NOT_VPN)
5391 .addTransportType(TRANSPORT_VPN)
5392 .build();
5393 NetworkCapabilities nc;
5394 mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
5395 vpnNetworkCallback.assertNoCallback();
5396
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005397 final TestNetworkAgentWrapper
5398 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anand4fa80e82019-02-06 10:13:38 -08005399 final ArraySet<UidRange> ranges = new ArraySet<>();
5400 ranges.add(new UidRange(uid, uid));
5401 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5402 mMockVpn.connect();
5403 mMockVpn.setUids(ranges);
lucaslin783f2212019-10-22 18:27:33 +08005404 vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
5405 false /* isStrictMode */);
Varun Anand4fa80e82019-02-06 10:13:38 -08005406
5407 vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
5408 nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
5409 assertTrue(nc.hasTransport(TRANSPORT_VPN));
5410 assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
5411 assertFalse(nc.hasTransport(TRANSPORT_WIFI));
5412 // By default, VPN is set to track default network (i.e. its underlying networks is null).
5413 // In case of no default network, VPN is considered metered.
5414 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
5415
5416 // Connect to Cell; Cell is the default network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005417 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anand4fa80e82019-02-06 10:13:38 -08005418 mCellNetworkAgent.connect(true);
5419
Chalard Jean6f4216f2019-06-05 01:40:32 +09005420 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5421 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005422 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005423 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005424
5425 // Connect to WiFi; WiFi is the new default.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005426 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anand4fa80e82019-02-06 10:13:38 -08005427 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5428 mWiFiNetworkAgent.connect(true);
5429
Chalard Jean6f4216f2019-06-05 01:40:32 +09005430 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5431 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005432 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005433 && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005434
5435 // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
5436 // the capabilities.
5437 mCellNetworkAgent.disconnect();
5438
5439 // Disconnect wifi too. Now we have no default network.
5440 mWiFiNetworkAgent.disconnect();
5441
Chalard Jean6f4216f2019-06-05 01:40:32 +09005442 vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
5443 (caps) -> caps.hasTransport(TRANSPORT_VPN)
Varun Anand4fa80e82019-02-06 10:13:38 -08005444 && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
Chalard Jean6f4216f2019-06-05 01:40:32 +09005445 && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
Varun Anand4fa80e82019-02-06 10:13:38 -08005446
5447 mMockVpn.disconnect();
5448 }
5449
5450 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005451 public void testIsActiveNetworkMeteredOverWifi() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005452 // Returns true by default when no network is available.
5453 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005454 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005455 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5456 mWiFiNetworkAgent.connect(true);
5457 waitForIdle();
5458
5459 assertFalse(mCm.isActiveNetworkMetered());
5460 }
5461
5462 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005463 public void testIsActiveNetworkMeteredOverCell() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005464 // Returns true by default when no network is available.
5465 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005466 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005467 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5468 mCellNetworkAgent.connect(true);
5469 waitForIdle();
5470
5471 assertTrue(mCm.isActiveNetworkMetered());
5472 }
5473
5474 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005475 public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005476 // Returns true by default when no network is available.
5477 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005478 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005479 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5480 mCellNetworkAgent.connect(true);
5481 waitForIdle();
5482 assertTrue(mCm.isActiveNetworkMetered());
5483
5484 // Connect VPN network. By default it is using current default network (Cell).
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005485 TestNetworkAgentWrapper
5486 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005487 final ArraySet<UidRange> ranges = new ArraySet<>();
5488 final int uid = Process.myUid();
5489 ranges.add(new UidRange(uid, uid));
5490 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5491 mMockVpn.setUids(ranges);
5492 vpnNetworkAgent.connect(true);
5493 mMockVpn.connect();
5494 waitForIdle();
5495 // Ensure VPN is now the active network.
5496 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5497
5498 // Expect VPN to be metered.
5499 assertTrue(mCm.isActiveNetworkMetered());
5500
5501 // Connect WiFi.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005502 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005503 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5504 mWiFiNetworkAgent.connect(true);
5505 waitForIdle();
5506 // VPN should still be the active network.
5507 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5508
5509 // Expect VPN to be unmetered as it should now be using WiFi (new default).
5510 assertFalse(mCm.isActiveNetworkMetered());
5511
5512 // Disconnecting Cell should not affect VPN's meteredness.
5513 mCellNetworkAgent.disconnect();
5514 waitForIdle();
5515
5516 assertFalse(mCm.isActiveNetworkMetered());
5517
5518 // Disconnect WiFi; Now there is no platform default network.
5519 mWiFiNetworkAgent.disconnect();
5520 waitForIdle();
5521
5522 // VPN without any underlying networks is treated as metered.
5523 assertTrue(mCm.isActiveNetworkMetered());
5524
5525 vpnNetworkAgent.disconnect();
5526 mMockVpn.disconnect();
5527 }
5528
5529 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005530 public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005531 // Returns true by default when no network is available.
5532 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005533 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Varun Anandc51b06d2019-02-25 17:22:02 -08005534 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5535 mCellNetworkAgent.connect(true);
5536 waitForIdle();
5537 assertTrue(mCm.isActiveNetworkMetered());
5538
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005539 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005540 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5541 mWiFiNetworkAgent.connect(true);
5542 waitForIdle();
5543 assertFalse(mCm.isActiveNetworkMetered());
5544
5545 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005546 TestNetworkAgentWrapper
5547 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005548 final ArraySet<UidRange> ranges = new ArraySet<>();
5549 final int uid = Process.myUid();
5550 ranges.add(new UidRange(uid, uid));
5551 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5552 mMockVpn.setUids(ranges);
5553 vpnNetworkAgent.connect(true);
5554 mMockVpn.connect();
5555 waitForIdle();
5556 // Ensure VPN is now the active network.
5557 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5558 // VPN is using Cell
5559 mService.setUnderlyingNetworksForVpn(
5560 new Network[] { mCellNetworkAgent.getNetwork() });
5561 waitForIdle();
5562
5563 // Expect VPN to be metered.
5564 assertTrue(mCm.isActiveNetworkMetered());
5565
5566 // VPN is now using WiFi
5567 mService.setUnderlyingNetworksForVpn(
5568 new Network[] { mWiFiNetworkAgent.getNetwork() });
5569 waitForIdle();
5570
5571 // Expect VPN to be unmetered
5572 assertFalse(mCm.isActiveNetworkMetered());
5573
5574 // VPN is using Cell | WiFi.
5575 mService.setUnderlyingNetworksForVpn(
5576 new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
5577 waitForIdle();
5578
5579 // Expect VPN to be metered.
5580 assertTrue(mCm.isActiveNetworkMetered());
5581
5582 // VPN is using WiFi | Cell.
5583 mService.setUnderlyingNetworksForVpn(
5584 new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
5585 waitForIdle();
5586
5587 // Order should not matter and VPN should still be metered.
5588 assertTrue(mCm.isActiveNetworkMetered());
5589
5590 // VPN is not using any underlying networks.
5591 mService.setUnderlyingNetworksForVpn(new Network[0]);
5592 waitForIdle();
5593
5594 // VPN without underlying networks is treated as metered.
5595 assertTrue(mCm.isActiveNetworkMetered());
5596
5597 vpnNetworkAgent.disconnect();
5598 mMockVpn.disconnect();
5599 }
5600
5601 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005602 public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
Varun Anandc51b06d2019-02-25 17:22:02 -08005603 // Returns true by default when no network is available.
5604 assertTrue(mCm.isActiveNetworkMetered());
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005605 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Varun Anandc51b06d2019-02-25 17:22:02 -08005606 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5607 mWiFiNetworkAgent.connect(true);
5608 waitForIdle();
5609 assertFalse(mCm.isActiveNetworkMetered());
5610
5611 // Connect VPN network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005612 TestNetworkAgentWrapper
5613 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Varun Anandc51b06d2019-02-25 17:22:02 -08005614 final ArraySet<UidRange> ranges = new ArraySet<>();
5615 final int uid = Process.myUid();
5616 ranges.add(new UidRange(uid, uid));
5617 mMockVpn.setNetworkAgent(vpnNetworkAgent);
5618 mMockVpn.setUids(ranges);
5619 vpnNetworkAgent.connect(true);
5620 mMockVpn.connectAsAlwaysMetered();
5621 waitForIdle();
5622 assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
5623
5624 // VPN is tracking current platform default (WiFi).
5625 mService.setUnderlyingNetworksForVpn(null);
5626 waitForIdle();
5627
5628 // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
5629 assertTrue(mCm.isActiveNetworkMetered());
5630
5631 // VPN explicitly declares WiFi as its underlying network.
5632 mService.setUnderlyingNetworksForVpn(
5633 new Network[] { mWiFiNetworkAgent.getNetwork() });
5634 waitForIdle();
5635
5636 // Doesn't really matter whether VPN declares its underlying networks explicitly.
5637 assertTrue(mCm.isActiveNetworkMetered());
5638
5639 // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
5640 // anyways suppose to be metered.
5641 mWiFiNetworkAgent.disconnect();
5642 waitForIdle();
5643
5644 assertTrue(mCm.isActiveNetworkMetered());
5645
5646 vpnNetworkAgent.disconnect();
5647 }
5648
5649 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005650 public void testNetworkBlockedStatus() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005651 final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
5652 final NetworkRequest cellRequest = new NetworkRequest.Builder()
5653 .addTransportType(TRANSPORT_CELLULAR)
5654 .build();
5655 mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
5656
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005657 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005658 mCellNetworkAgent.connect(true);
5659 cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5660
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005661 setUidRulesChanged(RULE_REJECT_ALL);
Mike Yuf9729752018-08-17 15:22:05 +08005662 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5663
5664 // ConnectivityService should cache it not to invoke the callback again.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005665 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005666 cellNetworkCallback.assertNoCallback();
5667
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005668 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005669 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5670
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005671 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005672 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
5673
5674 // Restrict the network based on UID rule and NOT_METERED capability change.
5675 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5676 cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5677 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5678 mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
5679 cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED,
5680 mCellNetworkAgent);
5681 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005682 setUidRulesChanged(RULE_ALLOW_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005683 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5684
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005685 setUidRulesChanged(RULE_NONE);
Mike Yuf9729752018-08-17 15:22:05 +08005686 cellNetworkCallback.assertNoCallback();
5687
5688 // Restrict the network based on BackgroundRestricted.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005689 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005690 cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005691 setRestrictBackgroundChanged(true);
Mike Yuf9729752018-08-17 15:22:05 +08005692 cellNetworkCallback.assertNoCallback();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005693 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005694 cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5695 cellNetworkCallback.assertNoCallback();
5696
5697 mCm.unregisterNetworkCallback(cellNetworkCallback);
5698 }
5699
5700 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005701 public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
Mike Yuf9729752018-08-17 15:22:05 +08005702 final TestNetworkCallback defaultCallback = new TestNetworkCallback();
5703 mCm.registerDefaultNetworkCallback(defaultCallback);
5704
5705 // No Networkcallbacks invoked before any network is active.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005706 setUidRulesChanged(RULE_REJECT_ALL);
5707 setUidRulesChanged(RULE_NONE);
5708 setUidRulesChanged(RULE_REJECT_METERED);
Mike Yuf9729752018-08-17 15:22:05 +08005709 defaultCallback.assertNoCallback();
5710
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005711 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Mike Yuf9729752018-08-17 15:22:05 +08005712 mCellNetworkAgent.connect(true);
5713 defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
5714 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent);
5715
5716 // Allow to use the network after switching to NOT_METERED network.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005717 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Mike Yuf9729752018-08-17 15:22:05 +08005718 mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5719 mWiFiNetworkAgent.connect(true);
5720 defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
5721
5722 // Switch to METERED network. Restrict the use of the network.
5723 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005724 defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005725 defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
5726
5727 // Network becomes NOT_METERED.
5728 mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
5729 defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent);
5730 defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent);
5731
5732 // Verify there's no Networkcallbacks invoked after data saver on/off.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005733 setRestrictBackgroundChanged(true);
5734 setRestrictBackgroundChanged(false);
Mike Yuf9729752018-08-17 15:22:05 +08005735 defaultCallback.assertNoCallback();
5736
5737 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005738 defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Mike Yuf9729752018-08-17 15:22:05 +08005739 defaultCallback.assertNoCallback();
5740
5741 mCm.unregisterNetworkCallback(defaultCallback);
5742 }
5743
Chalard Jeanb6ec0762019-12-03 16:12:33 +09005744 @Ignore // 40%+ flakiness : figure out why and re-enable.
Chalard Jean587758b2019-11-29 16:41:50 +09005745 @Test
5746 public final void testBatteryStatsNetworkType() throws Exception {
5747 final LinkProperties cellLp = new LinkProperties();
5748 cellLp.setInterfaceName("cell0");
5749 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5750 mCellNetworkAgent.connect(true);
5751 waitForIdle();
5752 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5753 TYPE_MOBILE);
5754 reset(mBatteryStatsService);
5755
5756 final LinkProperties wifiLp = new LinkProperties();
5757 wifiLp.setInterfaceName("wifi0");
5758 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
5759 mWiFiNetworkAgent.connect(true);
5760 waitForIdle();
5761 verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(),
5762 TYPE_WIFI);
5763 reset(mBatteryStatsService);
5764
Chalard Jean587758b2019-11-29 16:41:50 +09005765 mCellNetworkAgent.disconnect();
5766
5767 cellLp.setInterfaceName("wifi0");
5768 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
5769 mCellNetworkAgent.connect(true);
5770 waitForIdle();
5771 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5772 TYPE_MOBILE);
5773 }
5774
junyulai4a192e22018-06-13 15:00:37 +08005775 /**
5776 * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info.
5777 */
5778 private InterfaceConfiguration getClatInterfaceConfig(LinkAddress la) {
5779 InterfaceConfiguration cfg = new InterfaceConfiguration();
5780 cfg.setHardwareAddress("11:22:33:44:55:66");
5781 cfg.setLinkAddress(la);
5782 return cfg;
5783 }
5784
5785 /**
5786 * Make expected stack link properties, copied from Nat464Xlat.
5787 */
5788 private LinkProperties makeClatLinkProperties(LinkAddress la) {
5789 LinkAddress clatAddress = la;
5790 LinkProperties stacked = new LinkProperties();
5791 stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME);
5792 RouteInfo ipv4Default = new RouteInfo(
5793 new LinkAddress(Inet4Address.ANY, 0),
5794 clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME);
5795 stacked.addRoute(ipv4Default);
5796 stacked.addLinkAddress(clatAddress);
5797 return stacked;
5798 }
5799
5800 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005801 public void testStackedLinkProperties() throws Exception {
junyulai4a192e22018-06-13 15:00:37 +08005802 final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
5803 final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005804 final String kNat64PrefixString = "2001:db8:64:64:64:64::";
5805 final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
5806
junyulai4a192e22018-06-13 15:00:37 +08005807 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5808 .addTransportType(TRANSPORT_CELLULAR)
5809 .addCapability(NET_CAPABILITY_INTERNET)
5810 .build();
5811 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5812 mCm.registerNetworkCallback(networkRequest, networkCallback);
5813
Lorenzo Colittid593e292019-02-19 13:21:56 +09005814 // Prepare ipv6 only link properties.
junyulai4a192e22018-06-13 15:00:37 +08005815 final LinkProperties cellLp = new LinkProperties();
5816 cellLp.setInterfaceName(MOBILE_IFNAME);
5817 cellLp.addLinkAddress(myIpv6);
5818 cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
5819 cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005820 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
junyulai4a192e22018-06-13 15:00:37 +08005821 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08005822 reset(mMockDnsResolver);
Luke Huanga24d5d82019-04-09 18:41:49 +08005823 reset(mMockNetd);
Chalard Jean587758b2019-11-29 16:41:50 +09005824 reset(mBatteryStatsService);
junyulai4a192e22018-06-13 15:00:37 +08005825 when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
5826 .thenReturn(getClatInterfaceConfig(myIpv4));
5827
Lorenzo Colittid593e292019-02-19 13:21:56 +09005828 // Connect with ipv6 link properties. Expect prefix discovery to be started.
junyulai4a192e22018-06-13 15:00:37 +08005829 mCellNetworkAgent.connect(true);
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005830 final int cellNetId = mCellNetworkAgent.getNetwork().netId;
Chalard Jean587758b2019-11-29 16:41:50 +09005831 waitForIdle();
Luke Huanga24d5d82019-04-09 18:41:49 +08005832
5833 verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
5834 verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
Chalard Jean587758b2019-11-29 16:41:50 +09005835 verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
5836 TYPE_MOBILE);
Luke Huanga24d5d82019-04-09 18:41:49 +08005837
junyulai4a192e22018-06-13 15:00:37 +08005838 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005839 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005840
Lorenzo Colittid593e292019-02-19 13:21:56 +09005841 // Switching default network updates TCP buffer sizes.
5842 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
5843
5844 // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
5845 // the NAT64 prefix was removed because one was never discovered.
5846 cellLp.addLinkAddress(myIpv4);
5847 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005848 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005849 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
waynema13516842019-03-12 18:13:49 +08005850 verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005851
Chalard Jean587758b2019-11-29 16:41:50 +09005852 // Make sure BatteryStats was not told about any v4- interfaces, as none should have
5853 // come online yet.
5854 waitForIdle();
5855 verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt());
5856
Lorenzo Colittid593e292019-02-19 13:21:56 +09005857 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005858 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005859 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005860 reset(mMockDnsResolver);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005861
5862 // Remove IPv4 address. Expect prefix discovery to be started again.
5863 cellLp.removeLinkAddress(myIpv4);
5864 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5865 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005866 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005867 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005868
5869 // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005870 Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005871 assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
Lorenzo Colittid593e292019-02-19 13:21:56 +09005872 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5873 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005874 LinkProperties lpBeforeClat = networkCallback.expectCallback(
Chalard Jean059c4262019-09-30 17:51:12 +09005875 CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005876 assertEquals(0, lpBeforeClat.getStackedLinks().size());
5877 assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
5878 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5879
5880 // Clat iface comes up. Expect stacked link to be added.
junyulai4a192e22018-06-13 15:00:37 +08005881 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean059c4262019-09-30 17:51:12 +09005882 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005883 List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
5884 .getStackedLinks();
5885 assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
5886
5887 // Change trivial linkproperties and see if stacked link is preserved.
5888 cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
5889 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005890 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
junyulai4a192e22018-06-13 15:00:37 +08005891
5892 List<LinkProperties> stackedLpsAfterChange =
5893 mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
5894 assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
5895 assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
5896
Luke Huang65914772019-03-16 00:31:46 +08005897 verify(mMockDnsResolver, times(1)).setResolverConfiguration(
waynema13516842019-03-12 18:13:49 +08005898 mResolverParamsParcelCaptor.capture());
5899 ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
5900 assertEquals(1, resolvrParams.servers.length);
5901 assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
Luke Huang65914772019-03-16 00:31:46 +08005902
Chalard Jeanbbaa33e2019-11-19 19:03:53 +09005903 for (final LinkProperties stackedLp : stackedLpsAfterChange) {
5904 verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(),
5905 TYPE_MOBILE);
5906 }
Chalard Jean587758b2019-11-29 16:41:50 +09005907
Lorenzo Colittid593e292019-02-19 13:21:56 +09005908 // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
5909 // linkproperties are cleaned up.
junyulai4a192e22018-06-13 15:00:37 +08005910 cellLp.addLinkAddress(myIpv4);
5911 cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5912 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005913 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti9307ca22019-01-12 01:54:23 +09005914 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Luke Huang65914772019-03-16 00:31:46 +08005915 verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
junyulai4a192e22018-06-13 15:00:37 +08005916
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005917 // As soon as stop is called, the linkproperties lose the stacked interface.
Chalard Jean059c4262019-09-30 17:51:12 +09005918 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005919 LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
5920 LinkProperties expected = new LinkProperties(cellLp);
5921 expected.setNat64Prefix(kNat64Prefix);
5922 assertEquals(expected, actualLpAfterIpv4);
5923 assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
5924
5925 // The interface removed callback happens but has no effect after stop is called.
5926 clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
5927 networkCallback.assertNoCallback();
5928
Lorenzo Colittid593e292019-02-19 13:21:56 +09005929 verifyNoMoreInteractions(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005930 verifyNoMoreInteractions(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005931 reset(mMockNetd);
Luke Huang65914772019-03-16 00:31:46 +08005932 reset(mMockDnsResolver);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005933
Lorenzo Colittid593e292019-02-19 13:21:56 +09005934 // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
5935 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5936 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005937 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5938 (lp) -> lp.getNat64Prefix() == null);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005939
5940 // Remove IPv4 address and expect prefix discovery and clatd to be started again.
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005941 cellLp.removeLinkAddress(myIpv4);
5942 cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
5943 cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
5944 mCellNetworkAgent.sendLinkProperties(cellLp);
Chalard Jean059c4262019-09-30 17:51:12 +09005945 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Luke Huang65914772019-03-16 00:31:46 +08005946 verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
Lorenzo Colittid593e292019-02-19 13:21:56 +09005947 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
5948 kNat64PrefixString, 96);
Chalard Jean059c4262019-09-30 17:51:12 +09005949 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005950 verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
5951
Lorenzo Colittid593e292019-02-19 13:21:56 +09005952
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005953 // Clat iface comes up. Expect stacked link to be added.
5954 clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005955 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5956 (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005957
5958 // NAT64 prefix is removed. Expect that clat is stopped.
Lorenzo Colittid593e292019-02-19 13:21:56 +09005959 mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
5960 kNat64PrefixString, 96);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005961 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5962 (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005963 verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
Chalard Jean6f4216f2019-06-05 01:40:32 +09005964 networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
5965 (lp) -> lp.getStackedLinks().size() == 0);
Lorenzo Colitti6998fa82019-01-08 10:04:25 +09005966
5967 // Clean up.
junyulai4a192e22018-06-13 15:00:37 +08005968 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09005969 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Lorenzo Colitti2412c132019-01-22 09:47:54 +09005970 networkCallback.assertNoCallback();
junyulai4a192e22018-06-13 15:00:37 +08005971 mCm.unregisterNetworkCallback(networkCallback);
5972 }
Chiachang Wanga6093042018-09-28 22:42:48 +08005973
5974 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09005975 public void testDataActivityTracking() throws Exception {
Chiachang Wanga6093042018-09-28 22:42:48 +08005976 final TestNetworkCallback networkCallback = new TestNetworkCallback();
5977 final NetworkRequest networkRequest = new NetworkRequest.Builder()
5978 .addCapability(NET_CAPABILITY_INTERNET)
5979 .build();
5980 mCm.registerNetworkCallback(networkRequest, networkCallback);
5981
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005982 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chiachang Wanga6093042018-09-28 22:42:48 +08005983 final LinkProperties cellLp = new LinkProperties();
5984 cellLp.setInterfaceName(MOBILE_IFNAME);
5985 mCellNetworkAgent.sendLinkProperties(cellLp);
5986 reset(mNetworkManagementService);
5987 mCellNetworkAgent.connect(true);
5988 networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
5989 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
5990 eq(ConnectivityManager.TYPE_MOBILE));
5991
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09005992 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08005993 final LinkProperties wifiLp = new LinkProperties();
5994 wifiLp.setInterfaceName(WIFI_IFNAME);
5995 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
5996
5997 // Network switch
5998 reset(mNetworkManagementService);
5999 mWiFiNetworkAgent.connect(true);
6000 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006001 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006002 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6003 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
6004 eq(ConnectivityManager.TYPE_WIFI));
6005 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
6006
6007 // Disconnect wifi and switch back to cell
6008 reset(mNetworkManagementService);
6009 mWiFiNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006010 networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006011 assertNoCallbacks(networkCallback);
6012 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6013 verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
6014 eq(ConnectivityManager.TYPE_MOBILE));
6015
6016 // reconnect wifi
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006017 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Chiachang Wanga6093042018-09-28 22:42:48 +08006018 wifiLp.setInterfaceName(WIFI_IFNAME);
6019 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6020 mWiFiNetworkAgent.connect(true);
6021 networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
Chalard Jean059c4262019-09-30 17:51:12 +09006022 networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006023 networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
6024
6025 // Disconnect cell
6026 reset(mNetworkManagementService);
Luke Huang65914772019-03-16 00:31:46 +08006027 reset(mMockNetd);
Chiachang Wanga6093042018-09-28 22:42:48 +08006028 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006029 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
Chiachang Wanga6093042018-09-28 22:42:48 +08006030 // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
6031 // sent as network being switched. Ensure rule removal for cell will not be triggered
6032 // unexpectedly before network being removed.
6033 waitForIdle();
6034 verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
Luke Huang65914772019-03-16 00:31:46 +08006035 verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
6036 verify(mMockDnsResolver, times(1))
Luke Huanga24d5d82019-04-09 18:41:49 +08006037 .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
Chiachang Wanga6093042018-09-28 22:42:48 +08006038
6039 // Disconnect wifi
Chalard Jean407deb72019-11-19 16:14:30 +09006040 ConditionVariable cv = registerConnectivityBroadcast(1);
Chiachang Wanga6093042018-09-28 22:42:48 +08006041 reset(mNetworkManagementService);
6042 mWiFiNetworkAgent.disconnect();
6043 waitFor(cv);
6044 verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
6045
6046 // Clean up
6047 mCm.unregisterNetworkCallback(networkCallback);
6048 }
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006049
Chalard Jeane7b24752019-06-20 16:01:19 +09006050 private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006051 String[] values = tcpBufferSizes.split(",");
6052 String rmemValues = String.join(" ", values[0], values[1], values[2]);
6053 String wmemValues = String.join(" ", values[3], values[4], values[5]);
Chalard Jeane7b24752019-06-20 16:01:19 +09006054 verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006055 reset(mMockNetd);
6056 }
6057
6058 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006059 public void testTcpBufferReset() throws Exception {
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006060 final String testTcpBufferSizes = "1,2,3,4,5,6";
paulhu66269b32019-08-30 19:24:36 +08006061 final NetworkRequest networkRequest = new NetworkRequest.Builder()
6062 .addTransportType(TRANSPORT_CELLULAR)
6063 .addCapability(NET_CAPABILITY_INTERNET)
6064 .build();
6065 final TestNetworkCallback networkCallback = new TestNetworkCallback();
6066 mCm.registerNetworkCallback(networkRequest, networkCallback);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006067
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006068 mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006069 reset(mMockNetd);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006070 // Switching default network updates TCP buffer sizes.
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006071 mCellNetworkAgent.connect(false);
paulhu66269b32019-08-30 19:24:36 +08006072 networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006073 verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
6074
6075 // Change link Properties should have updated tcp buffer size.
6076 LinkProperties lp = new LinkProperties();
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006077 lp.setTcpBufferSizes(testTcpBufferSizes);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006078 mCellNetworkAgent.sendLinkProperties(lp);
Chalard Jean059c4262019-09-30 17:51:12 +09006079 networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
Lorenzo Colittif56ff042019-02-25 10:56:06 +09006080 verifyTcpBufferSizeChange(testTcpBufferSizes);
paulhu66269b32019-08-30 19:24:36 +08006081
6082 // Clean up.
6083 mCellNetworkAgent.disconnect();
Chalard Jean059c4262019-09-30 17:51:12 +09006084 networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
paulhu66269b32019-08-30 19:24:36 +08006085 networkCallback.assertNoCallback();
6086 mCm.unregisterNetworkCallback(networkCallback);
Chenbo Feng7f14dbc2018-11-08 17:36:21 -08006087 }
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006088
6089 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006090 public void testGetGlobalProxyForNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006091 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006092 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006093 final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
6094 when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
6095 assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
6096 }
6097
6098 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006099 public void testGetProxyForActiveNetwork() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006100 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006101 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006102 mWiFiNetworkAgent.connect(true);
6103 waitForIdle();
6104 assertNull(mService.getProxyForNetwork(null));
6105
6106 final LinkProperties testLinkProperties = new LinkProperties();
6107 testLinkProperties.setHttpProxy(testProxyInfo);
6108
6109 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6110 waitForIdle();
6111
6112 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6113 }
6114
6115 @Test
Chalard Jeane7b24752019-06-20 16:01:19 +09006116 public void testGetProxyForVPN() throws Exception {
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006117 final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
6118
6119 // Set up a WiFi network with no proxy
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006120 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006121 mWiFiNetworkAgent.connect(true);
6122 waitForIdle();
6123 assertNull(mService.getProxyForNetwork(null));
6124
6125 // Set up a VPN network with a proxy
6126 final int uid = Process.myUid();
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006127 final TestNetworkAgentWrapper
6128 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
Irina Dumitrescu044a4362018-12-05 16:19:47 +00006129 final ArraySet<UidRange> ranges = new ArraySet<>();
6130 ranges.add(new UidRange(uid, uid));
6131 mMockVpn.setUids(ranges);
6132 LinkProperties testLinkProperties = new LinkProperties();
6133 testLinkProperties.setHttpProxy(testProxyInfo);
6134 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6135 waitForIdle();
6136
6137 // Connect to VPN with proxy
6138 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6139 vpnNetworkAgent.connect(true);
6140 mMockVpn.connect();
6141 waitForIdle();
6142
6143 // Test that the VPN network returns a proxy, and the WiFi does not.
6144 assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6145 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6146 assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6147
6148 // Test that the VPN network returns no proxy when it is set to null.
6149 testLinkProperties.setHttpProxy(null);
6150 vpnNetworkAgent.sendLinkProperties(testLinkProperties);
6151 waitForIdle();
6152 assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
6153 assertNull(mService.getProxyForNetwork(null));
6154
6155 // Set WiFi proxy and check that the vpn proxy is still null.
6156 testLinkProperties.setHttpProxy(testProxyInfo);
6157 mWiFiNetworkAgent.sendLinkProperties(testLinkProperties);
6158 waitForIdle();
6159 assertNull(mService.getProxyForNetwork(null));
6160
6161 // Disconnect from VPN and check that the active network, which is now the WiFi, has the
6162 // correct proxy setting.
6163 vpnNetworkAgent.disconnect();
6164 waitForIdle();
6165 assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
6166 assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
6167 assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
6168 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006169
6170 @Test
6171 public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
6172 LinkProperties lp = new LinkProperties();
6173 lp.setInterfaceName("tun0");
6174 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6175 // The uid range needs to cover the test app so the network is visible to it.
6176 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006177 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006178
6179 // Connected VPN should have interface rules set up. There are two expected invocations,
6180 // one during VPN uid update, one during VPN LinkProperties update
6181 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6182 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6183 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6184 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6185 assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
6186
6187 vpnNetworkAgent.disconnect();
6188 waitForIdle();
6189
6190 // Disconnected VPN should have interface rules removed
6191 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6192 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6193 assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0"));
6194 }
6195
6196 @Test
6197 public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
6198 LinkProperties lp = new LinkProperties();
6199 lp.setInterfaceName("tun0");
6200 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6201 // The uid range needs to cover the test app so the network is visible to it.
6202 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006203 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6204 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006205
6206 // Legacy VPN should not have interface rules set up
6207 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6208 }
6209
Lorenzo Colitti8574c9b2019-04-12 19:50:22 +09006210 @Test
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006211 public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
6212 throws Exception {
6213 LinkProperties lp = new LinkProperties();
6214 lp.setInterfaceName("tun0");
6215 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
6216 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
6217 // The uid range needs to cover the test app so the network is visible to it.
6218 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006219 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
6220 lp, Process.SYSTEM_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006221
6222 // IPv6 unreachable route should not be misinterpreted as a default route
6223 verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
6224 }
6225
6226 @Test
6227 public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
6228 LinkProperties lp = new LinkProperties();
6229 lp.setInterfaceName("tun0");
6230 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
6231 // The uid range needs to cover the test app so the network is visible to it.
6232 final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006233 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006234
6235 // Connected VPN should have interface rules set up. There are two expected invocations,
6236 // one during VPN uid update, one during VPN LinkProperties update
6237 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6238 verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6239 assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
6240 assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
6241
6242 reset(mMockNetd);
6243 InOrder inOrder = inOrder(mMockNetd);
6244 lp.setInterfaceName("tun1");
6245 vpnNetworkAgent.sendLinkProperties(lp);
6246 waitForIdle();
6247 // VPN handover (switch to a new interface) should result in rules being updated (old rules
6248 // removed first, then new rules added)
6249 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6250 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6251 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6252 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6253
6254 reset(mMockNetd);
6255 lp = new LinkProperties();
6256 lp.setInterfaceName("tun1");
6257 lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
6258 vpnNetworkAgent.sendLinkProperties(lp);
6259 waitForIdle();
6260 // VPN not routing everything should no longer have interface filtering rules
6261 verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6262 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6263
6264 reset(mMockNetd);
6265 lp = new LinkProperties();
6266 lp.setInterfaceName("tun1");
6267 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6268 vpnNetworkAgent.sendLinkProperties(lp);
6269 waitForIdle();
6270 // Back to routing all IPv6 traffic should have filtering rules
6271 verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
6272 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6273 }
6274
6275 @Test
6276 public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
6277 LinkProperties lp = new LinkProperties();
6278 lp.setInterfaceName("tun0");
6279 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
6280 // The uid range needs to cover the test app so the network is visible to it.
6281 final UidRange vpnRange = UidRange.createForUser(VPN_USER);
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006282 final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006283 Collections.singleton(vpnRange));
6284
6285 reset(mMockNetd);
6286 InOrder inOrder = inOrder(mMockNetd);
6287
6288 // Update to new range which is old range minus APP1, i.e. only APP2
6289 final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
6290 new UidRange(vpnRange.start, APP1_UID - 1),
6291 new UidRange(APP1_UID + 1, vpnRange.stop)));
6292 vpnNetworkAgent.setUids(newRanges);
6293 waitForIdle();
6294
6295 ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
6296 // Verify old rules are removed before new rules are added
6297 inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
6298 assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
6299 inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture());
6300 assertContainsExactly(uidCaptor.getValue(), APP2_UID);
6301 }
6302
Valentin Iftimec86ebba2019-09-24 13:32:13 +02006303 @Test
6304 public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception {
6305 mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
6306
6307 LinkProperties wifiLp = new LinkProperties();
6308 wifiLp.setInterfaceName(WIFI_WOL_IFNAME);
6309 wifiLp.setWakeOnLanSupported(false);
6310
6311 // Default network switch should update ifaces.
6312 mWiFiNetworkAgent.connect(false);
6313 mWiFiNetworkAgent.sendLinkProperties(wifiLp);
6314 waitForIdle();
6315
6316 // ConnectivityService should have changed the WakeOnLanSupported to true
6317 wifiLp.setWakeOnLanSupported(true);
6318 assertEquals(wifiLp, mService.getActiveLinkProperties());
6319 }
6320
Qingxi Li7cf06622020-01-17 17:54:27 -08006321 @Test
6322 public void testNetworkCapabilitiesRestrictedForCallerPermissions() {
6323 int callerUid = Process.myUid();
6324 final NetworkCapabilities originalNc = new NetworkCapabilities();
6325 originalNc.setOwnerUid(callerUid);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006326
Qingxi Li7cf06622020-01-17 17:54:27 -08006327 final NetworkCapabilities newNc =
6328 mService.networkCapabilitiesRestrictedForCallerPermissions(
6329 originalNc, Process.myPid(), callerUid);
6330
6331 assertEquals(Process.INVALID_UID, newNc.getOwnerUid());
6332 }
6333
6334 private TestNetworkAgentWrapper establishVpn(
6335 LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
Remi NGUYEN VAN95dc87e2019-06-13 16:12:02 +09006336 final TestNetworkAgentWrapper
6337 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
Qingxi Li7cf06622020-01-17 17:54:27 -08006338 vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006339 mMockVpn.setNetworkAgent(vpnNetworkAgent);
6340 mMockVpn.connect();
6341 mMockVpn.setUids(vpnRange);
6342 vpnNetworkAgent.connect(true);
6343 waitForIdle();
6344 return vpnNetworkAgent;
6345 }
6346
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006347 private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
6348 final PackageInfo packageInfo = new PackageInfo();
paulhu86e23eb2019-11-05 18:05:05 +08006349 if (hasSystemPermission) {
6350 packageInfo.requestedPermissions = new String[] {
6351 CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS };
6352 packageInfo.requestedPermissionsFlags = new int[] {
6353 REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED };
6354 } else {
6355 packageInfo.requestedPermissions = new String[0];
6356 }
Lorenzo Colitti4c9f9542019-04-12 10:48:06 +00006357 packageInfo.applicationInfo = new ApplicationInfo();
6358 packageInfo.applicationInfo.privateFlags = 0;
6359 packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM,
6360 UserHandle.getAppId(uid));
6361 return packageInfo;
6362 }
Cody Kesting63e4e002019-12-18 10:57:50 -08006363
6364 @Test
6365 public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
6366 final NetworkRequest request =
6367 new NetworkRequest(
6368 new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
6369 try {
6370 mService.registerConnectivityDiagnosticsCallback(
6371 mConnectivityDiagnosticsCallback, request);
6372 fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
6373 } catch (IllegalArgumentException expected) {
6374 }
6375 }
6376
6377 @Test
6378 public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
6379 final NetworkRequest wifiRequest =
6380 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
6381
6382 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6383
6384 mService.registerConnectivityDiagnosticsCallback(
6385 mConnectivityDiagnosticsCallback, wifiRequest);
6386
6387 verify(mIBinder, timeout(TIMEOUT_MS))
6388 .linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
6389 assertTrue(
6390 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6391 mConnectivityDiagnosticsCallback));
6392
6393 mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
6394 verify(mIBinder, timeout(TIMEOUT_MS))
6395 .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
6396 assertFalse(
6397 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6398 mConnectivityDiagnosticsCallback));
6399 verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
6400 }
6401
6402 @Test
6403 public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
6404 final NetworkRequest wifiRequest =
6405 new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
6406 when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
6407
6408 mService.registerConnectivityDiagnosticsCallback(
6409 mConnectivityDiagnosticsCallback, wifiRequest);
6410
6411 verify(mIBinder, timeout(TIMEOUT_MS))
6412 .linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
6413 verify(mConnectivityDiagnosticsCallback).asBinder();
6414 assertTrue(
6415 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6416 mConnectivityDiagnosticsCallback));
6417
6418 // Register the same callback again
6419 mService.registerConnectivityDiagnosticsCallback(
6420 mConnectivityDiagnosticsCallback, wifiRequest);
6421
6422 // Block until all other events are done processing.
6423 HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
6424
6425 assertTrue(
6426 mService.mConnectivityDiagnosticsCallbacks.containsKey(
6427 mConnectivityDiagnosticsCallback));
6428 }
Jeff Sharkeyfb878b62012-07-26 18:32:30 -07006429}